rubber-duck-review について
現在のエージェントが作業の主導権を保ったまま、別モデルから読み取り専用のコードレビューを得るスキルです。レビュー担当の選択や範囲分割、結果整理を案内します。
主な機能
- 01現在と異なるレビュー担当モデルの選択
- 02読み取り専用レビューの実行
- 03大規模変更の並行レビュー
- 04関連変更に絞ったレビュー用プロンプト
- 05優先度付きの指摘を構造化
- 06CLIスクリプトによるレビュー起動
活用シーン
- 01コミット前の独立したコードレビュー
- 02大規模な差分を論理的な区分ごとにレビュー
- 03修正後の変更を再確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ vivswan/ skills --skill rubber-duck-reviewインストール後、Claude Code で/rubber-duck-reviewを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSE.mdREADME.md.codex-plugin/plugin.jsonagents/openai.yamlreferences/reviewer-prompt.mdscripts/run-review.mtsverdict-schema.jsonverdict.mts詳細
ラバーダックレビュー
タスクの主導権を保ちながら、別のモデルにコード変更についてセカンドオピニオンを求めます。
使用するタイミング
次のように依頼された場合に、このスキルを使用します。
/rubber-duck-review- 「変更内容をラバーダックレビューして」
- 「これについてセカンドオピニオンをもらって」
- 「別のモデルでこれをレビューして」
ワークフロー
1. レビュアーを選ぶ
- 専用のレビューツールがある場合は、そちらを優先します。
- 可能であれば、現在使用しているモデルとは異なるレビュアーを使用します。
- 専用ツールがない場合は、このスキルの
scripts/run-review.mtsを使って読み取り専用の CLI 呼び出しに切り替えます(ステップ 4)。現在使用しているモデルに応じてレビュアーを選びます。- 現在 Claude を使用している場合 →
codex、フォールバックはcopilot。 - 現在 Codex または GitHub Copilot を使用している場合 →
claude、フォールバックはcopilot。
- 現在 Claude を使用している場合 →
- レビュアーにファイルを書き込ませたり、コードを編集させたり、制限のないシェルコマンドを実行させたりしてはいけません。
- スクリプトは読み取り専用フラグを適用します。
--sandbox read-only(codex)/--permission-mode plan(claude)/読み取り専用ツールの許可リスト(copilot)。 - 読み取り専用でもレビュアーはセルフチェックできます。読み取り専用コマンド(grep、
git diff、typecheck)は実行できますが、書き込みはブロックされます。copilot はファイルの読み取りと grep のみ実行できます。こうしたセルフチェックにより、具体的な指摘が得られます。 - 注:読み取り専用サンドボックスでは一時ディレクトリの作成がブロックされることがあるため、書き込みを必要とするテストはスキップされる場合があります。
- codex 自身のサンドボックスを起動できない場合、スクリプトは代わりにサンドボックス外のスナップショットコピーをレビューします(ステップ 4)。これはファイルシステム上の制限が強制されないため、このルールの例外です。唯一の保護策はプロンプト内のレビューのみという指示であり、コピー先のパスを分けることで、禁止された書き込みがレビュー対象のチェックアウトに及ばないようにします。
- スクリプトは読み取り専用フラグを適用します。
2. 大規模な変更セット:セクションごとにレビューを並行実行する
- 大きな差分全体を一度にレビューすると、焦点を絞ったレビューを複数行うより浅くなります。変更を論理的な セクション(新しいコマンド/モジュールごと、スクリプトごと、CI/リリース設定、対応する一組のファイル)に分割します。各セクションの対象ファイルを指定して、レビューを 1 件ずつ並行して実行します。
- マシンとレビューバックエンドが停止せず処理できる数だけ、同時に実行してください。 最初は 3 件程度が安全です。
codex execを同時に多数実行すると、バックエンドが飽和してハングすることがあります。バッチが停止した場合は、数を増やすのではなく減らします。 - ハングを検出して復旧します。 JSON ストリーミングを使っている場合、各レビューのイベント数を約 30~60 秒間比較します。あるレビューのイベント数が変わらない一方で、ほかのレビューのイベント数が増えている場合、そのレビューはハングしています。それを停止し(タスクランナーの停止機能を使うか、起動時に表示されたそのプロセスの PID に対して
kill <the pid the launch printed>を実行します。パターンを使った kill は絶対に行いません)、そのレビューだけを再起動します。
3. プロンプトを作成する
- 関連する変更と周辺のコンテキストのみをレビューするよう依頼します。
- 必ず次の文を含めます。
This is a review-only task. Do not edit, write, or modify any files. Only read and report findings. - 差分を貼り付けるのではなく、収束ゲートが対象とするものと同じ対象名を指定し、変更内容の確認方法を伝えます。そうすることで、インポートやファイル間の挙動をより適切に追跡できます。
コミット前の場合は、「
git --no-pager diff --cachedを実行し、新しいファイルを読む」ことです。ブランチまたは PR の場合は、「ブランチの実際のベースを指定してgit --no-pager diff <base>...HEADを実行する」ことです。git diff HEADはどちらでもありません。コミット済みのブランチでは空になり、コミット前にはステージされていない編集が混ざります。 - レビュアーには、次の点を確認するよう依頼します。
-
正確性の問題
-
実証可能な不具合:正確性に関する指摘が作業対象となるのは、レビュー対象の変更において、具体的な入力または状態と、それによって生じる誤った出力、クラッシュ、またはデータ損失を明示している場合です。保守性に関する指摘が作業対象となるのは、次の箇条書きに従い、この変更内の具体的な箇所を指摘している場合です。
-
この変更で新たに生じた、すでに不自然な命名や設計上の選択:コードの現在の動作を誤解させる名前、またはこの変更で持ち込まれた重複や構造
-
長々とした正当化コメントで支えられている回避策:回避策が妥当だと主張するのに段落ほどのコメントが必要なら、そのコードは誤っています。コメントとコードの両方を修正対象として指摘します。
-
定例のライブラリに関する質問(原文のまま):「この変更で追加、移動、変更、再利用、または依存するコードの中に、このリポジトリにすでにある適切なライブラリやツールが行うことを行うものはありますか?その名前と、対応範囲を挙げてください。」移動または再利用されたヘルパーは、新規のものとしてレビューします。該当が確認された場合は
blocking指摘となります(/code-standardsスキルのルール)。大規模なライブラリ、または適合性が不明確な場合は、主張の冒頭を
Ask the owner:とし、ライブラリ名を挙げたblocking項目にします。ドライバーはこの質問をユーザーに提示し、回答があるまで何も作成しません。リポジトリが廃止したランタイムや API を必要とするライブラリは適合せず、指摘対象にもなりません。 -
定例のテストに関する質問:変更に含まれる各新規テストについて、そのテストが固定する事実をソースがすでに記述していないか確認します。レビュアーは、その事実を明示せずにテストを求めることはありません。
- 読み込むソースをそのまま言い換えるテストは、削除を修正とする指摘です。たとえば、ワークフローテストで
needsが YAML に記述されたリストと一致すると確認するもの、定数がそれ自身のリテラル値に固定されているもの、リポジトリに含まれる設定ファイルを読み込んで同じ内容であると確認するものです。 - テンプレートにはこの文言が含まれています。
/code-standardsスキルのテストに関する参照先で、ルール、3 つの有効な回答、および定数値を固定する別の場所を確認してください。
- 読み込むソースをそのまま言い換えるテストは、削除を修正とする指摘です。たとえば、ワークフローテストで
-
変更によって公開されるあらゆるものに含まれる PII:作成者が誰か、どのように作業するか、マシンがどのように設定されているかを読者に伝える情報で、作成者の実環境から測定またはコピーした値も含みます。すべてのフィクスチャは手作業で作成します。実データの出所を明記するコメントは指摘対象です。
テンプレートにはこの文言が含まれています。このルールと代替手段は
/pr-and-issue-disciplineスキルで確認してください。サンドボックス内のレビュアーが GitHub にアクセスできない場合があるため、PR のタイトル、本文、コメントをプロンプトに貼り付けます。 -
推測的な堅牢化(コードに到達できない悪意ある呼び出し元、シングルユーザー用ツールでの競合、外側のタイムアウトによってすでに制限されている期限、コードが受け取らない入力に対する防御的チェック)は、指摘ではなく
Recorded, not builtという見出しの下に記載します。ユーザーから依頼がない限り、実装しません。 外部ユーザーがいるリポジトリや、悪意ある入力にさらされるリポジトリ(公開パッケージや公開サービスなど)、またはユーザーが求めた場合は、代わりにユーザーに提示し、ユーザーの確認後にのみ実装します(ステップ 6)。レビュー対象の変更に付随する、小規模で明白な強化(バージョンチェックの横にある終了コードチェックなど)は、そのまま含めてもかまいません。レビュー担当者は、それを置き換えるために、より広範な強化を提案してはなりません。
-
- 関連スキルの基準を取り込みます。
## Review Criteriaセクションを含むSKILL.mdを宣言しているインストール済みスキルは、すべて、そのセクションをレビュー担当者向けプロンプトに展開します。そこで見つかった指摘は、そのスキル独自のワークフローに従って選別します。例外は、他者の PR の場合です。このときは、/reply-and-review-disciplineスキルの観点の選択によって、展開するセクションが決まります。- レジストリはありません。セクションを宣言していることが、そのスキルをレビューに含める条件です。このコレクションでは、
/no-invalid-states、/code-standards、/never-twice、/verify-with-controlsがこれを宣言しています。 - インストール済みスキルは、たとえば
grep -rlE '^## Review Criteria' ~/.claude/skills/*/SKILL.md .claude/skills/*/SKILL.md 2>/dev/nullで列挙します(スキルをインストールするハーネスに応じてパスを調整してください)。 - 基準が特定のコンテキストでのみ適用されるスキルは、見出しの名前を変えて(例:
## <Context> Review Criteria)、自身が起動するレビューに独自の基準を取り込みます。
- レジストリはありません。セクションを宣言していることが、そのスキルをレビューに含める条件です。このコレクションでは、
- 優先順位を付けた指摘(ブロッキングか非ブロッキングか)を求め、コードが正しい場合はその旨を明確に述べるよう求めます。これにより、再レビューを終わりのあるものにできます。
- レポートは 1 つの JSON オブジェクトです。
blockingとnon_blockingの配列には{where, claim, evidence}を含め、recorded_not_builtは文字列配列、summaryは要約とします。テンプレートからレポート形式のブロックを貼り付けます。スクリプトはscripts/verdict-schema.jsonを使って codex と claude の形式を検証します。copilot にはプロンプトしか与えられません。 - このスレッドでユーザーがすでに何かを却下または取り消している場合、レビュー担当者が同じ指摘を繰り返さないよう、短い
Already decided / out of scopeセクションを追加します。 - 再レビューでは、適用済みの修正を明記し、残りの項目に集中させます。
再利用可能なプロンプトテンプレートについては、references/reviewer-prompt.md を参照してください。
4. レビュー担当者を実行する
このスキルには scripts/run-review.mts が含まれています(パスはインストール済みスキルフォルダーを基準とし、レビュー対象リポジトリを基準とするものではありません)。このスクリプトは、起動時の落とし穴に対処します。
- シェルを介さず、argv 配列からレビュー担当者を起動します(プロンプト内のバッククォートや
$(...)はそのまま文字列として扱われます)。 - 標準入力を閉じます(
codex execとclaude -pは、開いたままの標準入力を待ち続けて停止するためです)。 - 出力全体を、作業ツリーではなく OS の一時ディレクトリにあるスクラッチファイルに保存します。
- verdict schema(codex と claude 用の
scripts/verdict-schema.jsonを含む)など、各レビュー担当者に必要なフラグを渡し、最終メッセージが自由形式のテキストにならないようにします。 - verdict を抽出し、その前にツール呼び出しがない場合は拒否します。codex は説明文もスキーマに入力するため、レビューを開始します」という文で終わるターンでも、形式上は空の verdict として成立してしまいます。必要な読み取りが欠けていることが、それを明らかにします。
- verdict、ツール呼び出し回数、保存されたキャプチャのパス、レビュー担当者の各ステップを 1 行ずつ示す簡潔な実行履歴を含む、JSON レポートを 1 つ出力します。ストリームを開かなくても、レビュー担当者が何をしたかを確認できます。
bun "<skill-dir>/scripts/run-review.mts" --help:
usage: run-review.mts <codex|claude|copilot> <prompt-file> [--background] [--stdin-prompt]
run-review.mts <codex|claude|copilot> --extract <output-file>
run-review.mts <codex|claude|copilot> --extract --wait <output-file> [--timeout <seconds>] (polls every 2 s; default timeout 3600)
run-review.mts <codex|claude|copilot> <prompt-file> --capture <dir> (internal)
run-review.mts prepare <section>
scratch (rubber-duck-*) lives under the OS tmp dir for 24 hours; prepare and a launch purge older ones
codex whose bubblewrap sandbox cannot start reviews an unsandboxed snapshot copy of the repository inside its scratch dir
prints: the JSON report (verdict, tool_calls, capture, trajectory, and sandbox only when codex fell back to copy mode); --background prints output-file: <path> and pid: <n>
exits: 0 verdict printed, or a --background launch started (its verdict comes via --extract);
1 review FAILED - relaunch: no usable verdict, whatever the cause, or --wait timed out; never a clean pass;
2 usage error, the reviewer binary not installed, or codex's sandbox unavailable outside a git repository
ステップ 3 のプロンプトを一時ファイルに書き込み、レビュー担当者の名前とそのファイルを渡します。1 台のマシンで複数のエージェント(または 1 つのファンアウト内の複数のセクション)が同時にレビューを行うことがあります。/tmp/rubber-duck-prompt-<section>.md のような予測可能な名前を使うと、スクリプトが読み取る前に別の書き込み元がそのプロンプトを上書きするおそれがあるため、スクリプトがパスを生成します。
prepare <section>はmkdtempで非公開ディレクトリを作成し(アトミックに作成されるため、2 つの呼び出し元に同じディレクトリが割り当てられることはありません)、マーカーをそこに残し、その中にあるセクションのプロンプトファイルのパスを出力します。- そのようなディレクトリの外にあるプロンプトファイルや、ディレクトリ内のシンボリックリンクまたはハードリンクを指定しても、起動は拒否されます。証明となるのは場所ではなくマーカーなので、2 つのシェルで同じ
TMPDIRを共有する必要はありません。
ハーネスのサンドボックスが、テキストに Git コマンドを含む Bash ヒアドキュメントを拒否する場合(一部のエージェントワークツリー環境では、コマンドがワークツリー内にとどまることを確認できないため拒否されます)、ハーネスのファイル書き込みツールを使ってプロンプトファイルを書き込みます。
# 1. Mint the prompt path, one call per review section. Shell state does not survive
# between tool calls, so copy the printed path by hand:
bun "<skill-dir>/scripts/run-review.mts" prepare api-gateway # prints e.g. /tmp/rubber-duck-prompt-Kq3mZp/api-gateway.md
# 2. Write the step-3 prompt to that path with the harness's file-writing tool (a heredoc
# with a quoted delimiter serves where the sandbox allows it).
# 3. Then, in one shell call:
prompt_file="/tmp/rubber-duck-prompt-Kq3mZp/api-gateway.md"
bun "<skill-dir>/scripts/run-review.mts" codex "$prompt_file" # codex|claude|copilot per step 1
- レビュアーの引数:
codex:codex exec --json --sandbox read-only --output-schema <schema>を実行します。- 起動時に、まず
codex sandbox -- trueでサンドボックスを確認します。codex はサンドボックス内のすべてのコマンドを bubblewrap の下で実行します。AppArmor プロファイルがマウントの伝播を拒否するコンテナでは、起動時に次のエラーが発生します:bwrap: Failed to make / slave: Permission denied。 - この拒否が起きた場合に限り、起動方法を切り替えます。スクリプトは git を使ってリポジトリのスナップショットをレビュー用の一時ディレクトリに作成し、そのコピー内で、
--sandbox danger-full-accessを指定して codex を実行します。作業ディレクトリに追跡対象のファイルがない場合は、コピーのルートが実行場所になります。 - スナップショットに含まれるのは、git がコミット済み、またはコミット対象として認識している内容です。ブランチ名での HEAD、すべての ref(
ORIG_HEADとFETCH_HEADを含む)、および作業ツリーとしてチェックアウトされたインデックスが含まれ、チェックアウトとオブジェクトストアを共有します。部分クローンの promisor remote も引き継がれるため、チェックアウトでまだ取得していない blob は、最初に読み込む際に取得されます。そのため、git diff --cachedとgit diff <base>...HEADは、コピー内で同じ変更を表示します。 - それ以外は引き継がれません。ステージされていない編集、未追跡ファイル、無視されたツリー(インストール済みの依存関係やネストされたワークツリー)、サブモジュールの内容、チェックアウトの設定はコピーに含まれません。Git LFS のファイルはポインターのままで、スパースチェックアウトもそのままです。数ギガバイトのチェックアウトでは、追跡対象ファイルのサイズ分のスナップショットが作成されます。また、インストール済みの依存関係が必要な型チェックやテストは、コピー内では実行できません。
- レビュアーの終了時にコピーは削除されます(削除できなかった場合は
review.errにnot removedとして記録されます)。レポートと起動記録にはsandbox: "copy"が記載されます。標準エラー出力には、拒否の理由とコピーのパスが記録されます。 - レビュアーは、ユーザーの
config.tomlとauth.jsonのコピーを含む一時的なCODEX_HOMEの下で実行されます。codex は起動したディレクトリを信頼済みプロジェクトとして設定ファイルに書き込みます。コピーのパスはレビューごとに新しくなるため、この書き込みは一時ホームに行われ、そこが削除されると消えます。 - ユーザー自身の設定ファイルに書き込まれることはありません。ただし、codex が一時的な
auth.jsonに書き込んだトークンの更新情報は、codex が永続化を想定しているため、ユーザーのファイルにも反映されます。 - 一時ホームの
sessionsディレクトリはユーザー自身のディレクトリへのリンクです。そのため、レビューのトランスクリプト(codex のセッションの記録)は、読み取り専用で起動した場合と同様にユーザーのホームに保存され、クリーンアップ後も残ります。 - git リポジトリの外ではスナップショットを作成できないため、終了コード 2 で終了します。その他の確認エラー(サブコマンドに対応していない古い codex など)の場合は、読み取り専用での起動を維持します。
- 起動時に、まず
claude:claude -p --permission-mode plan --verbose --output-format stream-json --json-schema <schema>を実行します(stream-jsonでは--verboseが必須です)。copilot:copilot -p <prompt> -s --available-tools=view,rg,glob --deny-tool=write --deny-tool=shell --disable-builtin-mcpsを実行します。最終手段のフォールバックなので、codex または claude を優先してください。制限事項は次のとおりです。- 読み取り専用ツールの許可リストにより、ファイルの読み取りと grep はできますが、シェルの実行、書き込み、MCP サーバーへの接続、サブエージェントの起動はできません。
- シェルを使えないため、
git diffや型チェックは実行できません。読み取るファイルを指定してください。 - JSON をストリーミングしないため、稼働状況を示すシグナルも、レポート内の実行履歴も、判定に対するツール呼び出しのチェックもありません。スキーマを指定するフラグがないため、JSON オブジェクトを要求するのはプロンプトだけです。
--stdin-prompt(codex/claude のみ):環境がコマンド引数としてのプロンプトを拒否する場合、またはプロンプトが非常に大きい場合に追加します。プロンプトファイル自体がレビュアーの標準入力として渡されます。 fd は EOF で終了するため、ハングすることはありません。stdin のハングを引き起こすのは、使用済みの stdin ではなく、開いたままのパイプです。- フォアグラウンド(デフォルト)ではレビュアーが終了するまでブロックされるため、ツール呼び出しには余裕のある明示的なタイムアウトを指定してください。サブエージェント(worktree ビルダー、起動されたワーカー)は、起動をフォアグラウンドで実行するか、
--backgroundを指定してから、上限時間を設けたフォアグラウンド呼び出しで待機します(ステップ 5)。バックグラウンドのレビュアーからの完了通知を待ちながらターンを終えるワーカーには、その通知は届きません。 --backgroundは、output-file: <path>とpid: <n>のちょうど 2 行を出力します。output-fileはキャプチャされたストリームです。デタッチされたモニターがレビュアーの終了ステータスをその横に記録します。- リードは、レビューの実行中も作業を続け、
--extract --waitで判定結果を取得するために使います(ステップ 5)。サブエージェントは、1 回のフォアグラウンド呼び出しを超える可能性があるレビューに使い、ステップ 5 の上限付き待機を行います。 - その PID を終了するとレビューがキャンセルされます(シグナルはレビュアーに転送されます)。
- 進捗状況:フォアグラウンド実行では、ストリームに最初の出力が現れたときとレビュアーが終了したときに、stderr に最大 2 行の進捗メッセージが表示されます(失敗時はさらに
review FAILED行が追加されます。codex コピー モードでは、その前に通知が追加されます)。その間に何も表示されないのは通常です。実際のレビューには時間がかかる場合があります。 - ランタイム:
bunです。node24+ も動作します(node "<skill-dir>/scripts/run-review.mts" ...)。 - 終了コード:上記の使用方法ブロックの
exits:行を参照してください。各終了コードへの対処方法はステップ 5 に記載されています。 - 同梱されているスクリプトとこれらの引用(レビュアーの呼び出し、フラグ、失敗判定)は、上流で同期されています。また、使用方法ブロックがスクリプトと一致することをテストで確認しています。食い違いがある場合は、スクリプトを優先し、その差異を報告してください。
5. 出力された判定に対応する
-
フォアグラウンド実行または
--extractの終了コード 0:stdout には 1 つの JSON レポートが出力されます。(--backgroundの起動も終了コード 0 となり、出力パスと PID のみが表示されます。判定結果は--extractで取得します。)verdict.blockingとverdict.non_blocking:指摘事項が{where, claim, evidence}の形式で列挙されています。ステップ 6~7 に従ってトリアージし、それぞれ適用するか却下してください。verdict.recorded_not_built:レビュアーが保留にした、推測に基づく堅牢化案です。これへの対応はステップ 6 に記載されています。verdict.summary:レビュー対象と方法です。単に「コードは正しい」と述べているだけの場合は、修正後の再レビューを省略する理由ではなく、収束に向けた情報として扱ってください。tool_calls、trajectory:判定前に実行された読み取りやコマンドの数と、レビュアーの各ステップを簡潔にまとめた行です。変更されたファイルの読み取りがなく、git diffだけが 1 回示されているtrajectoryの判定は、レビューとして不十分です。プロンプトを具体化してファイル名を明記し、再実行してください。capture:24 時間保持される、レビュアーのストリーム全体です。指摘や要約に違和感があり、レビュアーの正確なメッセージを確認したい場合は読み取ってください。
-
終了コード 1(
review FAILED - relaunch):これはレビューがまったく行われていない状態であり、合格ではありません。再実行してください。これは、ストリームが空だった、ターンの途中で切れた、最終行が途中で切り詰められた、失敗したターンまたは判定に続かないエラーが含まれていた、判定オブジェクト以外のメッセージで終了した、ツール呼び出しの前に判定が出た(前置き)、またはレビュアーが 0 以外で終了したことを意味します。キャプチャされたストリームがまだ残っている場合、失敗メッセージにそのパスが示されます。
-
終了コード 2:呼び出しを修正するか、不足しているレビュアーのバイナリをインストールしてください。レビューは行われていません。
-
--backgroundで起動した後の判定待ちには、実行主体ごとに 2 つの方法があります。異なる理由は 1 つだけです。長時間の呼び出し 1 回の後でアイドル状態になったサブエージェントは起こされませんが、バックグラウンドコマンドの終了時にリードのセッションは再度呼び出されます。リード(ハーネスによって再度呼び出されるセッション)は、1 つのバックグラウンドシェルで待機し、ハーネスから完了通知を受け取ります。
review.statusや出力パスを手動でポーリングしてはいけません。out=<the path from the output-file: line> bun "<skill-dir>/scripts/run-review.mts" <reviewer> --extract --wait "$out" --timeout 3600 > "${out%/*}/verdict.out" 2>&1サブエージェント(worktree ビルダー、起動されたワーカー)は、最初に
--backgroundを付けて起動し、その後、判定、失敗行、または停滞行が出るまでこの呼び出しを繰り返します。各実行はそれぞれ独立したフォアグラウンドのツール呼び出しで、Bash の timeout パラメーターは 300000 ms に設定します。out=<the path from the output-file: line>; record="${out%/*}/review.status" ! grep -q '"status"' "$record" && find "$record" -mmin +60 | grep -q . && { echo "review stalled: no verdict an hour after the launch; report it to the lead"; exit 3; } bun "<skill-dir>/scripts/run-review.mts" <reviewer> --extract --wait "$out" --timeout 240次の手順を決めるのは呼び出しの出力であり、終了コードだけではありません。終了コード 1 は、タイムアウトした待機と失敗したレビューの両方に使われるためです。
呼び出しの出力 意味 次の手順 stdout に JSON レポート、終了コード 0 判定が出ました 以下に従って対応します stderr に review FAILED - relaunch (--wait timed out: ...)、終了コード 1まだ判定は出ていません 呼び出しを再実行します stderr に review FAILED - relaunch (<any other reason>)、終了コード 1レビューが失敗しました 再起動します review stalled: ...、終了コード 3起動記録が 1 時間経過しても statusがありません。これは起動側ではなく、このブロック固有の上限です停滞をリードに報告します 待機は毎回、短いフォアグラウンド呼び出しとして繰り返します。長い呼び出しを 1 回だけ行うことはありません。各待機はそれぞれ独立したフォアグラウンドのツール呼び出しであり、シェルループにはしません。シェルループも結局は長い呼び出し 1 回になるためです。
/orchestrator-modeスキルのreferences/spawn-briefs.mdにある「停止して待つことの禁止」には、ブロックの側に関する説明があり、ここを参照するよう記載されています。どちらの形式でも、以下のとおりです。
<reviewer>は、レビューの起動時に指定した引数です。- リードの判定は、そのレビューのキャプチャディレクトリ内にある
verdict.outに書き込まれるため、並行して実行されるレビュー(ステップ 2)が互いの結果を上書きすることはありません。判定ファイルはディレクトリとともに移動し、ディレクトリの削除時に削除されます。サブエージェントのフォアグラウンド呼び出しは、ツールの結果として判定を出力します。 - スクリプトは、モニターが終了を記録するまで 2 秒ごとに起動記録をポーリングし、その後、同じ JSON レポートを出力します。
--timeout <seconds>(デフォルトは 3600)が先に経過すると、stderr に--wait timed outという理由を出力して終了コード 1 で終了し、レポートは出力しません。 - reviewer と出力ファイルを起動記録の内容と照合して検証します。そのため、誤った reviewer やファイルを待機した場合、または起動記録のないファイルを待機した場合は、終了コード 2 で直ちに失敗します。
- リードが 1 回だけ行う待機でも、上の表と同じ行を読み取ります。ただし、違いが 1 つあります。タイムアウトを含め、
review FAILED - relaunchの行はすべて再起動を意味します。
-
bun "<skill-dir>/scripts/run-review.mts" <reviewer> --extract <output-file>を--waitなしで実行すると、完了済みの実行を 1 回だけ読み取ります。reviewer がまだ実行中の場合はブロックせず、終了コード 1(no exit status recorded)で終了します。 -
reviewer まで到達した実行では、スクラッチディレクトリが 24 時間保持されます(OS の一時ディレクトリ内で、作業ツリー内には作成されません)。対象は、レポート内の
captureパスを含むディレクトリ、または失敗時のoutput kept atパスです(該当ストリームがすでに存在しない場合は省略されます)。スクリプトはプロンプトのスナップショットをそのディレクトリに保存するため、起動側が書き込んだものはすべて一緒に移動し、一緒に削除されます。- どの起動モードでも、reviewer 自身のトランスクリプトは codex のもので、そのホームディレクトリに保存されます。
prepareと各起動処理では、24 時間を超えた兄弟のrubber-duck-*ディレクトリを、経過時間だけを基準にして最初に削除します。これにより、作成したプロンプトディレクトリも同じ 24 時間保持されます。24 時間未満のディレクトリは別セッションで実行中のレビューなのでそのまま残し、シンボリックリンクはたどりません。削除に失敗した場合は stderr に報告しますが、レビューは失敗しません。- 自分の 2 つのディレクトリを早めに削除するには、その 2 つだけを削除してください。共有一時ディレクトリ内で glob を使ってはいけません。そこで
rubber-duck-*を一括削除すると、他のセッションで進行中のレビューが終了してしまいます。 - 一括削除可能な領域を使いたいセッションは、起動前に自分で作成したディレクトリを
TMPDIRに設定します。prepareと起動処理の両方がこの設定に従います。 - reviewer のバイナリが見つからないフォアグラウンド起動(終了コード 2)では、何もキャプチャされず、後に残るものもありません。
--backgroundで起動した場合は、--extractでバイナリが見つからないことを報告できるよう、ディレクトリが保持されるため、その後に削除してください。
6. 調査結果を適切に反映する
-
有効な「非ブロッキング」のフィードバックが、この変更で実証された影響を伴う正確性または保守性に関する指摘であれば、実際の作業として扱います。
- 同じ変更に伴う、簡潔で明白な強化(バージョンチェックの横に終了コードのチェックを追加する、引数のひとつとして上限値を設けるなど)は問題ありません。
- 歯止めをかけるべきなのは、レビューのたびに前回の強化を回避する仮説がさらにひとつ見つかり、対象範囲が広がっていくことです。最初のラウンドで決めた最小限の形を維持し、それ以外は
Recorded, not builtに記録します。後のラウンドで実証可能な不具合が見つかった場合は、引き続き最初の箇条書きに従って作業します。 Recorded, not builtに記載した項目は作業対象ではありません。ユーザーから依頼がない限り、レポートに残し、タスクや PR は作成しないでください。ただし、外部ユーザーがいるリポジトリや、悪意ある入力にさらされる領域(公開パッケージや公開サービスなど)は例外です。その場合は具体的なリスクをユーザーに伝え、ユーザーが確認した項目だけを実装します。
-
ブロッキングの指摘だけでなく、有効な非ブロッキングの指摘も修正します。保守性を高める修正(より明確な命名、重複の削除、構造の簡素化など)も含みます。
- 主張が
Ask the owner:で始まるblockingの項目は、指摘ではなく質問です。ライブラリ名を示してユーザーに質問し、回答があるまでは実装しません。ほかのブロッキングの指摘と同様に、回答を得るまで変更を保留します。 - 修正が設計に反する場合、レビュー対象の変更範囲を超える場合、または明示されたユーザーの決定に反する場合に限り、有効な指摘を見送ります。その理由を記録してください。
- 変更が依存するコードについて、ライブラリに関する指摘が確認された場合、それを変更範囲外として見送ることはできません。
/code-standardsスキルのルールに従い、フォローアップタスク、課題、またはセッションのタスクリストに追加します。規模の大きいライブラリや、対応が不明確な場合は、まずオーナーの回答を待ちます。 - 指摘が誤り、または適用外だと判断した場合は、見送るのではなく、次の箇条書きに従って却下します。
- 主張が
-
すべての指摘を無批判に受け入れないでください。異議がある場合は、その理由を説明し、設計に反する修正(正当な経路を壊すガードの追加など)にも注意してください。
-
テストで検証する事実をソースの記述以上に特定していない「テストを追加する」という指摘は、どのレビュアーによるものであっても、その理由を添えて却下します。独自の動作がない削除は、テストではなく PR 本文またはマージ報告に記載する調査結果で証明します。
-
指摘が明示されたユーザーの決定に反する場合は、ユーザーに従い、その問題を意図的に見送ったことを記録します。
-
修正をまとめて適用するたびに、再レビューの前に再検証します。言語に型チェックがある場合はそれを実施し、変更とその検証に関係するテストを実行します。CI でいずれにせよ実行されるテスト一式は実行しません。実行時間の長い処理には明示的なタイムアウトを設定し、プロセスはパターンではなく、自分が起動した PID を指定して停止します。
CI の実行時間が課金対象、または限られている場合(従量制プランのプライベートリポジトリなど)は、プッシュ前にローカルでチェック一式を一度実行します。どちらに該当するかわからない場合は、ユーザーまたは説明を受けたリーダーに確認してください。
7. 収束するまで再レビューする
-
修正を適用した後、更新された状態を対象に、セクションごとに1回ずつレビューを再実行します。全体をまとめて1回レビューするのではありません。
-
有効なブロッキング指摘がなくなり、すべての非ブロッキング指摘がステップ6に従って処理されるまで繰り返します。処理方法は、修正する、記録した理由を添えて見送る、または誤りや適用外として却下する、のいずれかです。
これが収束の唯一の判定基準です。レビューが収束するまで、変更はコミットもマージもされません。コミット時に対象となるのはステージ済みの差分です。Git がコミットするのは作業ツリーではなくインデックスだからです。マージ時に対象となるのは、ブランチまたは PR の差分です。
これがレビュー収束の唯一の定義です。これをゲートとするスキル(例:
/pr-landing-disciplineの Converged)は、この定義を言い換えるのではなく、ここを参照してください。 -
収束したレポートには、レビューの基準としたルーブリックを明記します。 プロンプトファイルのパス、または基準と「すでに決定済み」の項目を1行にまとめたものを記載します。指示は実行中に変わることがあり、「収束した」という報告を読むリードは、どのバージョンを基準に収束したのかを確認する必要があります。
例:3人のビルダーが「収束した」と報告しましたが、レビュー中にオーナーが差し替えたルーブリックを基準にしていました。報告にはそれを示す情報がありませんでした。各報告に1行あれば分かることでした。
8. この指示が機能しない場合は、スキルを修正する
- ステップが実際の作業で失敗し、その根本原因が指示自体にある場合(記載されているフラグがすでに存在しない、抽出ルールで判定を取得できない、コピー&ペースト用のブロックが再現可能な形で動作しないなど)は、スキルを修正します。
- まず回避策を使って現在のレビューを完了し、次回に同じ問題が再発しないよう修正内容を記録します。
- その前に、一時的な原因(バックエンドの障害、サンドボックスの制限、ローカルツールの設定)を除外します。これらはスキルの欠陥ではありません。
- これは、指示を推進するエージェントであるあなたにも適用されます。 レビュアーはステップ1に従い、読み取り専用のままです。
- スキルの正規ソースを編集できる場合に限り、スキルを修正します。つまり、作成元のリポジトリで、該当するスキルのソース(
SKILL.md、references/、またはscripts/)を直接編集します。 - インストール済みまたはベンダー提供のコピーしかない場合、あるいは書き込み権限がない場合は、欠陥と修正案をユーザーに報告します。
- スキルの正規ソースを編集できる場合に限り、スキルを修正します。つまり、作成元のリポジトリで、該当するスキルのソース(
- 根本原因は、一時的な注記として追加するのではなく、該当するステップに反映します。コピー&ペースト用のブロックは、記載どおりに実行できる状態に保ちます。
- スキルの編集も、他の変更と同様に作業ツリー上の変更です。修正済みの指示を対象にレビューを完了し、その編集にも同じ検証・レビュー・収束のゲート(ステップ6および7)を適用します。