コンテンツにスキップ

LLMO監査: 二段レビュー

すでにパターンを理解していて、コマンドだけ欲しい場合:

Terminal window
# 1. 監査プロンプトを保存(サイト固有に編集する)
cat > /tmp/audit-prompt.md <<'EOF'
この Astro サイトを SEO/LLMO/構成の観点でレビュー。src/ と dist/ の両方を見る。
P0/P1/P2 のファイルパス付き発見を出力。診断のみ — ファイル編集はしない。
EOF
# 2. codex を read-only サンドボックスで実行、出力をファイルへ(</dev/null 必須)
codex exec -C /path/to/repo -s read-only --skip-git-repo-check \
-o /tmp/codex-review.md \
"$(cat /tmp/audit-prompt.md)" </dev/null
# 3. トリアージ
less /tmp/codex-review.md

</dev/null は必須 — これが無いと、非対話シェルから起動した codex exec が stdin 待ちでハングする。

以下の本文では、その「なぜ」と「どう」を説明する。

LLMO実装をリリースした。JSON-LDを配置した。llms.txt を作った。Schema.orgエンティティはバリデータを通った。自分でレビューもした。一通り完成して見える。

半年後、監査でこれらが発見される:

  • レイアウトに <slot name="head" /> の宣言が抜けていた。リリース以降、ページ別 JSON-LDはすべて silent drop されていた。エラーなし、警告なし、テスト失敗なし — 書いたメタデータが届かないままサイトは動いていた
  • サブページ間の内部リンクに末尾スラッシュが無く、クリックのたびに301リダイレクトが発生し、正規URLシグナルが曖昧になっていた
  • フッターは「Kindle 4冊」と書いてあるのに、トップページのプロフィールは「14冊」になっていた。著者がトップだけ更新してフッターを忘れたまま、AIクローラには両方が数ヶ月配信され続けていた
  • 404ページの canonical は /404/(Astroが生成したルート)を指しているが、GitHub Pages は実際には /404.html を配信していた。共有された404 URLは正規シグナルとずれていた

これらはどれも、自分が書いたコードでは見つけにくい。正しく書いたと記憶している部分は、無意識に読み飛ばす。昨日正しかった面は今日も正しいと仮定する。意図を知っているからこそレビューがバイアスを持つ。

事前情報を持たない第二のレビュアー——リポジトリ・dist出力・本番サイトに実際に存在するものだけを見る目線——が必要になる。

パターンはシンプル: まず自分でレビューし、次に独立したAIエージェントに read-only モードで同じ成果物を見せる。2つの段階は補完関係にある:

段階レビュアー検出されるもの
第1段自分(または同じセッション内の通常のAIアシスタント)表層の修正、「ここはこうあるべき」型の問題
第2段read-only サンドボックスの独立AI意図と現実のドリフト、silent failure、自分が気付いていない仮定

第2段は自分の変更のコードレビューではない — 結果状態の監査である。レビュアーは「あなたが何をしようとしたか」に関心を持たず、「デプロイされたシステムが実際に何をしているか」だけを見る。

これは科学論文の peer review と構造的に類似している: 著者は内部論理の妥当性を確認し、レビュアーは外部主張の妥当性を確認する。LLMOにおいて、第1段は「計画通りに実装したか?」を、第2段は「実装は実際に意図通り動くか?」を検証する。

なぜAIのセカンドオピニオンか(自分で読み返すのではダメか)

Section titled “なぜAIのセカンドオピニオンか(自分で読み返すのではダメか)”

自分で読み返すのは第1段と同じバイアスのかかったパスだ — 自分の書いた部分を目が依然として読み飛ばす。静的リンタは構文の問題を捕えるが、面ごとの意味のドリフトは捉えない。人間のレビュアーは理想的だが、コストが高く、非同期である。

read-onlyモードでリポジトリに対して走るAIエージェントは、別のスイートスポットに当たる:

  • 意図に対する事前情報を持たない。disk と dist/ 上にあるものだけを見る
  • すべてを読む。100個目のFAQエントリーを読んでも、自分のように飽きない
  • 速くて再現可能。リリースごとに4分のパスは安い
  • 構造化された出力を返す。grep / diff し、次の反復に流し込める

コストとして、AIは false positive を返したり、極めて文脈依存の問題を見逃したりすることがある。出力は決定ではなくトリアージキューとして扱う。

以下の例は OpenAI Codex CLI を使用するが、read-only サンドボックスを持つ任意のエージェントCLIで動作する(Claude Code、Aider 等)。

1. プロンプトをファイルに書く

Section titled “1. プロンプトをファイルに書く”

プロンプトは最重要資産だ。1度20分かけて書けば、すべてのリリースで再利用できる監査ハーネスになる。

# {サイト} 全体LLMOレビュー
`/path/to/repo` の Astro サイト(公開URL: `https://example.com`)を以下の観点でレビューしてください:
- SEO: meta、hreflang、canonical、og:*、twitter:*、sitemap エントリ
- LLMO: llms.txt、JSON-LD エンティティ、/ai/ Markdown 面、URL.md エンドポイント
- 構成: 多言語カバレッジ、死リンク、内部ナビゲーション
- 出力検証: 書いた JSON-LD は実際に出力されているか?
各発見について以下を出力してください:
- ファイルパス
- 具体的な問題(バイト列を引用)
- 推奨修正
P0(即修正)/ P1(高)/ P2(任意)でグルーピング。
最後にカテゴリ別サマリ表を入れる。
ファイル編集は禁止。診断のみ。

AIには、どの種類の成果物を見るかを明示的に指示する: 実際に配信されるHTMLは dist/、ソースは src/。このヒントがないと、ソースだけ読んで出力側のバグを見逃すことがある。

2. read-only サンドボックスで起動

Section titled “2. read-only サンドボックスで起動”
Terminal window
codex exec \
-C /path/to/repo \
-s read-only \
--skip-git-repo-check \
-o /tmp/codex-review.md \
"$(cat /tmp/review-prompt.md)" \
</dev/null

2つのフラグが重要:

  • -s read-only(サンドボックス): AIは試みても編集できない。監査対象を変更せずにドリフトを捉えるために必須
  • </dev/null: stdinを明示的にクローズ。これがないと、非対話シェルから起動した codex exec がユーザー入力待ちで永久ハングする可能性がある

-o フラグで最終レポートをファイルに書く。stdoutにも出したい場合は tee でパイプする。

発見はP0/P1/P2のバケツで返ってくる。優先度順に処理する:

  • P0 は検証する。本番サイトまたは dist/ で再現確認。再現すれば修正
  • P1 は評価する。本物のバグもあれば、スタイル選好もある。changelog に記録して判断
  • P2 はアーカイブ。フォローアップタスクとして残す

AIの推奨をそのままマージしない。AIはパッチを提案できるが、コードを書くのはあなただ — 検証してテストしてリリースする。

二段パターンが実際に何を捕えるか

Section titled “二段パターンが実際に何を捕えるか”

2026年5月に2つの本番サイトに対して実施した自己監査の結果(重複除外):

発見タイプ第1段で検出第2段で検出
OG画像404 / og:type 重複
翻訳コンテンツの字音記号脱落
内部リンクの末尾スラッシュ抜け
静的ページの hreflang
dead slot="head"(JSON-LD silent drop)
クロスファイル数値ドリフト(4冊 vs 14冊)
/ai/ 配下の www. と apex 混在
全ページへのJSON-LD過剰注入
404 og:url と実配信URLの不一致
<table> + <a> で生成される invalid HTML
og:locale が /en/ ページでも ja_JP のまま
同一住所が異なる2つの Organization エンティティに分かれる
コンポーネントツリー改善(Header/Footer の i18n)

第2段が捕えた発見は、すべて意図と現実が乖離していた箇所だ。ソース上は正しく見えるが、デプロイされた成果物が一致していない。第1段のレビューでは出力を明示的に検証しない限り、これは見えない。

  • メジャーリリースごと: 全体二段レビューを実施。AI実行時間 ~5分、人間のトリアージ時間 ~30分
  • 四半期コンテンツ監査ごと: ファイル間の数値ドリフト(著書数、PV統計、サービスカタログ)を明示的にチェックするプロンプトに更新して再実行
  • マイグレーションごと(ホスト変更、CMS変更、フレームワークアップグレード): 必須。マイグレーション直後は意図-現実ドリフトが最も大きい

codex exec --sandbox read-only を一般的なコンテンツサイト(~50ファイル、~10K LoC)に対して実行するAPIトークンコストは、セント〜数ドル程度。すべてのリリースのゲートにかけられる安さである。

  • 第2段を書き込み権限で走らせる。AIが修正を始めて監査シグナルを失う。-s read-only(または同等オプション)を使う
  • 第2段を同じセッション内の同じエージェントにやらせる。バイアスを引き継ぐ。別プロセスで新しいエージェントを起動する — 別モデル、別会話、別ワーキングセット
  • 第2段を最終決定として扱う。第2段は候補を示す。検証し、判断し、修正し、再実行する
  • プロンプトファイルを書かない。インラインプロンプトはドリフトする。audits/ ディレクトリにバージョン管理されたプロンプトファイルを置けば、リリース間の発見を比較できる
  • 監査プロンプトがリポジトリ内にバージョン管理されている(シェル履歴ではない)
  • プロンプトがソースと dist/(または本番URL)の両方を見るよう明示的に指示している
  • プロンプトが P0/P1/P2 でファイルパス付きの発見を求めている
  • 監査が read-only サンドボックスで動き、レビュアーがファイルを変更できない
  • stdin が明示的にクローズされている(</dev/null)。エージェントが入力待ちでハングするのを防ぐ
  • 出力が grep/diff 可能なファイルに書き出される
  • 発見が課題管理システムに振り分けられる。自動マージはしない
  • 監査ケイデンスが文書化されている(リリースごと / 四半期ごと / マイグレーションごと)