このコードベースの対立監査を実行し、完了させてください。まずレポートと成果物を提出し、ソースコードは --fix が指定された場合、またはユーザーが修正を選択した場合にのみ変更します。
あなたは 敵対者 です。各レンズは異なる角度から1つの質問を投げかけます。どのような入力、タイミング、ユーザー、または攻撃者が、このコードに誤った回答をさせ、データを喪失・漏洩させ、またはユーザーを困らせるでしょうか?
このフォルダには監査に必要なすべてが含まれています。以下のパスはこのファイルのディレクトリから解決します。
lenses/<lens>.md:レンズごとに1ファイル。Fires:行はレンズが起動するタイミングを指定します(always、またはwhen <condition>)。各プローブは 無条件(常に回答)または(when <condition>)とマークされます(条件が成立する場合にのみ回答、そうでなければ該当なしとしてクローズ)。その後、レンズが生成するアーティファクトとその完了行が続きます。scripts/scan.py:リポジトリをフィンガープリントし、レンズをルーティングし、プロジェクト独自のアナライザーをリストアップします。scripts/signals.tsv:すべての検出とシードパターン。scripts/tools.tsv:既知の全アナライザー。プロジェクトはdocs/agents/audit-signals.tsvに独自の行を追加できます。scripts/verify.py:発見ファイルをレンズファイルに対してチェックします。scripts/cochange.sh:一緒に変更されるファイル。DELIVER.md:引き継ぎメモ、監査マップとそのチケット。UNTANGLE.md:構造的リファクタリング。--untangleおよび構造的チケット用。
1. スコープ
- 引数:パス(デフォルト: リポジトリルート)、
--lens a,b(指定レンズのみ実行)、--since REF(指定リファレンス以降の変更を監査。PRベースまたは前回監査のコミット)、--fix、--untangle [area|ticket](UNTANGLE.mdに直接スキップ)、--out DIR(デフォルト.audit/)。 - 回答が得られない場合(CI、
claude -p)、未回答の質問はHANDOFF.mdに未解決質問として残され、成果物はローカルトラッカーのみに配信され、チケットがapproved:行にない限りソースは変更されません。 - 出力ディレクトリを作成し、
*を含む.gitignoreを配置することで、監査が追跡対象ファイルに触れないようにします。新しい実行を開始するとき(再開時は除く)、まず以前の実行のRUN.md、REPORT.md、findings/を<out>/history/<実行日>/に移動し、新しい実行がそれらと比較できるようにします。 - 再開:
<out>/HANDOFF.mdが存在する場合、nextフェーズから続行し、実行ファイルはそのままにします。approved:行にあるチケットは、再度確認せずにソース変更が許可されます。フロンティアの最初のチケットを、セッションごとに1チケット、DELIVER.mdの指示に従って処理します。その他のチケットは先にユーザーに戻します。history/に以前の実行が存在する場合、--since <そのコミット>を提案し、refuted.mdを前方に持ち越します。
以下の各フェーズは、DELIVER.md の説明に従って <out>/HANDOFF.md を書き換えて終了します。
2. スキャンと偵察
python3 scripts/scan.py <path> [--since REF] [--lens a,b] > <out>/SCAN.md を実行します。SCAN.md はスクリプトの生の出力です。スタック、パッケージ、どのレンズが起動するかとその理由、ホットスポット、実行計画、実行するアナライザー、プローブごとの候補サイト(最もホットなファイルから順)、特別なケースの数。
ツール にリストされ、コマンドが利用可能な各アナライザーを実行し、その出力を <out>/tools/<tool>.txt に保存します。それらの警告は、スキャンサイトと同様に各行が指定するレンズのリードになります。欠落または失敗したツールは RECON.md に記録され、インストールはされません。
次に <out>/RECON.md を書き、スクリプトでは見えない部分を補完します。すべての見出しに回答または none が記入された場合にのみ完了します。
- 境界:外部データが侵入するすべての場所(HTTP、Webhook、DB読み取り、ファイル、環境変数、ディープリンク、プッシュペイロード、モデル出力、ユーザー入力)。
- 永続化:ローカルストア、サーバーDB、キャッシュ、キュー、および各事実を所有するもの。
- クリティカルパス:マネー、認証、データ削除、マイグレーション、安全性に関わるもの、メインユーザーループ。
- コマンド:ビルド、テスト、リント、実行。テストが現在合格するかどうか。
- ハウスルール:
CLAUDE.md/AGENTS.md。GLOSSARY.md(またはGLOSSARY-MAP.md)のドメイン言語。発見と修正のすべての名前で使用します。ADR。受け入れられたリスクは、リスクが変わらない限り確定とみなします。docs/agents/の課題トラッカー。 - 条件:各起動レンズについて、どの条件付きプローブがここで成立するか、その証拠とともに。
- レンズのオーバーライド:スキャンでスキップされたが偵察で必要と判断されたレンズ、または誤ったシグナルで起動したレンズとその理由。
<out>/RUN.md を書きます。コミット、日付、引数、最終的なレンズリスト。
3. ハンティング
スキャンの計画に従います。逐次:各レンズをここで1つずつ実行。並列:各レンズにサブエージェントを与え、シャード化されたレンズにはリストされたパッケージごとに1つのサブエージェントを与えます。同時実行数に上限があるホストでは、最もサイト数の少ないレンズをペアにしてウェーブを実行します。サブエージェントを持たないホストでは、すべてを逐次実行します。
サブエージェントはスキルなし、この会話なしで開始するため、各ブリーフは単独で完結します。ブリーフには以下を含めます:レンズファイル、このファイル(メソッド と 発見フォーマット 用)、RECON.md、SCAN.md の該当レンズセクション、スコープ、出力パス <out>/findings/<lens>[-<package>].md。ハンターは読み取り専用のリーフです。コードを読み、テスト、スクリプト、アプリを実行し、発見ファイルと再現手順のみを書き、メインコンテキストに戻ります。メインコンテキストのみがディスパッチします。
メソッド
- プレモーテム:ローンチから3か月後、この分野に関するトップの1つ星レビューを書いてみてください。次に、それを引き起こしたコードを見つけてください。
- 逆転:この機能を可能な限りひどく失敗させるにはどうすればよいですか?各方法でコードブロックを確認してください。
- 仮定台帳:クリティカルパス上の各関数について、何を仮定しているかをリストアップしてください。型や制約で強制されているものと、希望に依存しているものはどれですか?
- チェスタトンのフェンス:ガード、特殊ケース、または奇妙な行をバグと呼ぶ前に、なぜそれが存在するのかを見つけてください(
git log -L、blame、PR)。理由が生きているフェンスは発見ではありません。 - 候補はリード:スキャンサイトは読み始める場所です。サイトがゼロのプローブでも回答が必要であり、具体的なシナリオがある場合にのみサイトは発見になります。
発見フォーマット
### <LENS>-<n> <60文字以内の主張>
- where: パス:行
- probe: <レンズファイルからのプローブID>
- scenario: <具体的な入力、状態、タイミング> → <ユーザーまたはシステムが目にする誤った結果>
- severity: critical | high | medium | low
- detectability: loud (クラッシュ、アラート、テスト失敗) | quiet (誰かが気付くかもしれない誤った回答) | silent (誰も気付かない)
- verdict: CONFIRMED (<再現したテスト、スクリプト、クエリ、スクリーンショット>) | PLAUSIBLE (推論された、実行されていない)
- fix family: <変更の種類、パッチそのものではない>
深刻度:criticalはデータの喪失・破損、セキュリティ・プライバシーの侵害、金銭の誤り、または安全性のリスクを引き起こします。highは一般的なパスで誤った回答を示すか、ユーザーを困らせます。mediumは稀なパスでそうするか、品質を低下させます。lowは衛生上の問題です。深刻度は、出荷設定で今日誰がトリガーできるかによって設定されます。criticalまたはhighのシナリオはその人を特定します(任意の訪問者、任意のサインインユーザー、Xを保持する攻撃者)。オペレーターのみが到達するパスまたはデッドコンフィグは1レベル下げます。
編集:発見、再現手順、レポート、チケットは共有されます。秘密、トークン、個人データの代わりに <REDACTED> と書き、それを引用する代わりにその場所を指してください。
発見ファイルはレンズのアーティファクトで始まります。すべてのプローブは少なくとも1つの発見または1つの clean: 行で終わります。clean: <probe> — <evidence>、または条件付きプローブで条件が成立しない場合、clean: <probe> — n/a: <why>。ハンターは、完了行が成立し、python3 scripts/verify.py <out> --root <path> --lens <lens> がパスしたときに完了します。
4. 検証
- 重複のマージ:レンズ間で重複する発見。2つの発見が場所とメカニズムを共有する場合、より深刻なブロックを残し、
- also: <他のID>を追加し、もう一方のブロックを削除します。これにより、各問題が1回だけ表示されます。 - 反論:すべてのcriticalまたはhighの発見には新しい反論者(refuter)が割り当てられます。残りはレンズごとにバッチ処理されます。反論者は発見ブロックのみを受け取り、ハンターの推論は受け取りません。
PLAUSIBLEの発見に対しては、主張を否定しようとします:上流のガード、DBの制約、到達不可能なパス、理由のあるフェンス。CONFIRMEDの発見に対しては、再現手順をチェックします:述べられた理由で、実際のユーザーや攻撃者が到達するコードを通じて、エラーになるか?ホストが異なるモデルを提供する場合、反論者はそれを使用します。同じモデルでの同意は弱い証拠であるためです。 - 証拠による昇格:生き残りかつ再現 →
CONFIRMED。推論のみで生き残り →PLAUSIBLE。否定された → 理由とともに<out>/refuted.mdへ。 - カバレッジ批評家:新しいサブエージェント1つが
RECON.mdのクリティカルパスとすべてのレンズのclean:行を受け取り、証拠が薄い(トレースやテストが必要だったのに一文だけ)クリティカルパス、またはどのレンズも到達しなかったクリティカルパスを特定します。それぞれが、レポートの前に2回目の調査のために該当するレンズに戻されます。
再現手順は タイトな フィードバックループであり、この発見でのみ エラー になります。最も近いシームでの失敗テスト、スクリプト、クエリ。10分以内に構築できるものは、<out>/repro/ に、ローカル、ブランチ、サンドボックス、またはテストモードのシステムに対してのみ構築します。来四半期も有効な理由(受け入れられたリスク、意図的なトレードオフ)によって否定された発見は、ADRに属し、配信時に提供されるため、後の監査で偵察時に読み込まれます。
5. レポート
<out>/REPORT.md を書きます。
- 概要:深刻度とレンズ別の件数、および最初に行うべき3つの修正とその理由。
- 修正:発見を根本原因でクラスタリングします。各修正は、それが解決する発見の上に書かれます。複数の発見の背後にある1つの修正を探します。それは発見自体とは似ていないことがよくあります。各修正に
structural(結合、重複、欠落した型、浅いモジュール、誤ったシーム、アダプター)またはlocal(1つの場所、1つの変更)のタグを付け、構造的修正は深いモジュールの語彙で説明します:モジュール、インターフェース、深さ、シーム、アダプター、レバレッジ、局所性、削除テスト。 - クラスタリングされていない発見:深刻度、次に検出可能性(サイレント優先)、次に到達可能性でランク付け。
- カバレッジ:すべてのレンズの
clean:行、スキップされたレンズとその理由、実行または欠落したアナライザー、カバレッジ批評家が返した内容。 - 前回の監査以降:
history/に以前の実行がある場合:修正済み、未解決、新規、および回帰(以前修正されたが再発)。
- サーバーを `scan_count` の唯一の書き込み側にし、`where scan_count > 0` でアトミックにデクリメントすることで、クライアントがドリフト、二重使用、またはリセットできないようにする。[structural, critical]
- MONEY-2 `ScanQuota.swift:40` アップロード前にローカルでデクリメントし、リトライ時にも再度デクリメントする。
- MONEY-3 アプリの再インストールによりローカルストレージの `scansUsed` が0にリセットされる。
- STATE-5 週間クォータがデバイスのローカル月曜日にリセットされるため、西に飛ぶと2週目が得られる。
python3 scripts/verify.py <out> --root <path> を実行します。レポートは検証に合格すると最終版と見なされます。ホストが構造化された発見(ReportFindings ツール)をレンダリングする場合、すべての生き残った発見を最も深刻なものから順にそこにも報告します。
ファネルを調整する:サイトがすべて反論またはクリーンになったシード行、またはどのシードも指さなかった発見は、プロジェクトの docs/agents/audit-signals.tsv への提案行です。提案をレポートにリストします。ユーザーが受け入れた場合にのみ書き込まれます。
6. 配信と引き継ぎ
DELIVER.md を読んでください。レポートを、修正ごとに1チケット、型指定、ブロッキングエッジ付きで、リポジトリの課題トラッカー(設定がない場合はローカルの .scratch/、リモートトラッカーに投稿する前に確認)に監査マップとして描画します。次に、どの修正を1ラウンドの グリリング として開始するかを尋ねます。各修正に推奨回答付きの質問として番号を付け、「はい」がそれを受け入れるような文言にします。--fix の場合、すべての推奨を受け入れます。承認されたチケット番号を HANDOFF.md の approved: 行に記録します。
各チケットをその形状に従ってルーティングします。名前付きスキルは mattpocock-skills のものです。利用可能な場合は Skill ツールで呼び出し、そうでない場合はインラインでそのステップを実行します。
| チケットの形状 | ルート |
|---|---|
| 最初に決定が必要:シームの場所、矛盾するADR、曖昧なドメイン用語、受け入れるリスク | grill-with-docs:回答をADRと用語集として記録 |
| 構造的、1モジュール、コミット前にユーザーと検討する価値あり | improve-codebase-architecture をそのエリアに |
| 構造的、競合するインターフェース設計 | codebase-design、その design-it-twice パターン |
| 構造的、道筋は明確で1セッションに収まる | UNTANGLE.md、チケットと REPORT.md を開始リストとして |
| 構造的、1セッションより大きい | wayfinder、宛先に向かって決定チケットをチャート化 |
| 無人で作業するエージェント用にスライスする多数の修正 | to-tickets(tracer-bullet スライス、ブロッキングエッジ、expand–contract としての広範囲リファクタリング)、次に implement |
| ローカル修正 | tdd:再現手順が最初のレッドテストであり、ユーザーと合意したシームで。フルスイートはグリーンのまま |
PLAUSIBLE かつ critical、まだ再現手順なし | diagnosing-bugs フェーズ1:最初にタイトなループを構築 |
フロンティアが空になったら、--since <監査コミット> で再監査します。監査の目的地は、生き残ったcriticalまたはhighの発見なしで検証に合格する再監査です。
完了条件
- すべての起動したレンズが完了行を満たす発見ファイルを持ち、
verify.pyが出力全体でパスする。 - すべての生き残った発見に場所、プローブ、シナリオ、深刻度、検出可能性、評決がある。すべての否定された発見は
refuted.mdにある。 REPORT.mdがすべての発見を修正の下またはクラスタリングされていないリストに配置し、マップが修正ごとに1チケットを持ち、HANDOFF.mdが次のチケットを指定している。