repo-review — リポジトリ包括レビュー
棲み分け(先に確認)
| 目的 | スキル |
|---|---|
| 実績数値を正確に計測して SSOT/経歴書に記録 | code-metrics |
| 品質・設計を評価して改善案を出す(本スキル) | repo-review |
| 差分(PR/コミット)のレビュー | engineering:code-review |
| 複数LLMに批評させて改訂案を作る | multi-llm-review |
本スキルはコードを変更しない(レビューのみ)。
大原則(これを破ったレビューは価値がない)
- 推測で数値を書かない。 実行して数える。実行できなかったものは「未検証」と明記する
- 一般論を書かない。 すべての指摘に
file:lineまたは関数名を引用する - 根拠のない称賛を書かない。 強みにも実測の裏付けを付ける
- 終了コードを信じない。 出力本文を読んで成功を判定する(後述 Phase 3)
Phase -1: 既存レビューの検出(🔴 最初にやる・省略禁止)
同じリポジトリが既にレビュー済みかを必ず先に調べる。 調べずに始めると、前回より粗いレビューを やり直して「新発見」として報告する事故が起きる。
# 1. バックログに完了済み/進行中のレビュータスクがないか
grep -n "包括レビュー\|repo-review\|レビュー" ~/projects/obsidian-ssot/00_SYSTEM/バックログ.md | grep -i "<repo名>"
# 2. 過去のレビュー記録(_INDEX.md は信じず実ファイルを直接見る)
ls ~/projects/obsidian-ssot/01_DECISIONS/<repo名>/ | grep -iE "レビュー|review|監査|audit"
# 3. 未マージのリモートブランチ上にレビューが無いか(ローカルだけ見ると取りこぼす)
git -C <REPO> fetch origin && git -C <REPO> branch -r | grep -iE "review|audit"
# 4. CI実行履歴のタイトルに既存レビューが無いか(← ここでしか気づけないケースがある)
gh run list --limit 10 -R <owner>/<repo>
探索先は4つとも見ること。 SSOT(01_DECISIONS/)とバックログだけでは、
未マージブランチ上・CI履歴上のレビューを取りこぼす。
見つかった場合の分岐
| 状況 | 対応 |
|---|---|
| 完了済みレビューがある | 差分レビューに切り替える。前回の実測値を読み込み、今回は「前回から何が変わったか・前回の指摘は解消されたか・前回が見ていない観点」に絞る。同じ数値を再掲しない |
| 進行中(🟢)のレビューがある | 重複着手の soft 警告をユーザーに出す(active-sessions.md 参照) |
| 未マージのレビューブランチがある | そのブランチの内容を先に確認する。マージ判断がバックログに残っていないか調べる |
| 何も無い | 通常フロー(Phase 0 へ) |
⚠️ 実例1(2026-08-13・CI履歴でしか気づけなかった):
atelier-kyo-managerのレビュー時、 既存レビューが未マージのリモートブランチ上にあり、SSOT とdocs/を見ても発見できなかった。 偶然gh run listの displayTitle(「包括的リポジトリレビュー(2026-08-12)」)で気づいたが、 気づかなければ14指摘を初出のように再掲していた。⚠️ 実例2(本スキル自身が踏んだ): 2026-08-17 に
atelier-kyo-managerをレビューしたが、 08-13 に別セッションが同じプロンプトで実施済みだった(バックログ L304[x])。 しかも前回のほうが詳細で(CC平均5.64/中央値4・型注釈率73.4%・エンドポイント103中99が@login_required)、P0の機能停止級バグ(Celery配線)まで発見・修正済みだった。 さらに悪いことに、バックログには既に 「repo-comprehensive-review.md プロンプト改良(既存レビュー検出手順の追加)」というタスクが 起票されていた(L250)。その存在に気づかず、まさにその問題を再演した。
教訓: 過去経緯の探索は _INDEX.md を信じずバックログと実ファイルを直接 grep する
(00_SYSTEM/チャーター.md「読者前提」・rules/_shared/LLMサボりバイアス防止.md「タスク再着手時の必須検索」)。
Pre-flight: 浅い用途でないかの確認(1問・Phase 0 の前)
スキル発火時に最初に1問だけ確認する:
「タイポ確認・特定ファイル1つの指摘など浅い用途ではありませんか? (浅いなら本スキルでなく 通常のRead/Grepで対応します。包括評価ならこのまま進めます)」
浅い用途に大掛かりな6 Phaseを回すのは過剰(ユーザー・トークンの無駄)。包括評価のみ Phase 0 へ進む。
Phase 0: リポジトリ種別の判定(Phase -1 の次・省略禁止)
種別を誤ると評価軸ごと間違える。 以下を測ってから分類する。
python3 <skill>/scripts/repo_metrics.py <REPO>
| 種別 | 判定条件(暫定閾値) | 評価軸 |
|---|---|---|
| アプリケーション | コードLOC > ドキュメントLOC・エントリポイントあり(main/実行スクリプト) | 全6観点(標準) |
| ライブラリ/SDK | 公開APIがある・利用側リポジトリが別・エントリポイントなし | API安定性・後方互換・型定義を重視 |
| 運用スクリプト集 | 依存宣言なし・src/ なし・CI薄い |
「実行手段の文書化」「再現性」を重視。カバレッジは問わない |
| コンテンツ | ドキュメントLOC > コードLOC×3(目安 3:1超) | コード品質より「コンテンツの検証ゲート」の有無を評価 |
| ハイブリッド(複合型) | 複数種別の条件を同時に満たす(例: コンテンツ+運用スクリプト) | 両評価軸をマージして両方報告 |
判定ルール(暫定閾値・フェイルセーフ)
- 閾値は暫定。判定に迷ったら必ずフルレビュー側(アプリケーション評価軸)へ倒す(フェイルセーフ: 浅く評価して見落とす害 > 深く評価して手間が増える害)
- スタックマーカーが複数ある(モノレポ)場合は、サブディレクトリごとに種別判定と評価軸を分ける
(例:
web/はアプリ・packages/lib/はライブラリ・docs/はコンテンツ) - 判定根拠(どのLOC・マーカーで分類したか)は Phase 2.5 で検証するので残しておく
⚠️ 実例:
zennは記事18,093行 vs コード1,283行(12.6:1)。package.jsonがあるため素朴には "Node/JS-TS アプリ" と判定されるが、JS/TS のコードは0行(zenn-cli用の設定ファイルだった)。 スタック判定は「設定ファイルの存在」でなく「実際のコードLOC」で裏取りすること。
Phase 1: 除外の確定(🔴 最重要・ユーザー確認必須)
固定の除外リストは新しい生態系に必ず負ける。 機械的に候補を列挙してユーザーに確認する。
1-1. 既定の除外
正典はスクリプト側 scripts/_shared.py の DEFAULT_EXCLUDE(単一ソース・2026-08-18 critical対応)。
.git node_modules vendor .venv venv dist build target
__pycache__ .next coverage .mypy_cache .pytest_cache .ruff_cache htmlcov
.gradio mutants site-packages .terraform
除外指定はベース名(node_modules)とパス(backend/plugins)の両方が効く(_shared.py prune_dirnames)。
対象リポジトリの生成物ディレクトリはパス指定で除外する。
1-2. 候補の機械的検出(既定リストで足りない分)
トップレベルの各ディレクトリについて LOC を出し、次に該当するものを除外候補として提示する:
- ディレクトリ名に
plugin/cache/marketplace/example/sample/fixture/third_party/externalを含む - 同一ファイルが2箇所以上に存在する(
cache/とmarketplaces/のような二重取り込み) - リポジトリ総LOCの 30%以上を単独で占めるが、コミット履歴にほとんど出てこない
🔍 除外候補(確認してください)
plugins/ 271,207 LOC ← 外部プラグイン取込・cache/ と重複
skills/ 183,232 LOC ← マーケットプレイス由来
.claude/ 110,815 LOC
これらを除外しますか?[y / 個別指定]
⚠️ 実例:
claude-configで除外しなかった場合 Python 88,330行と出たが、実体は 18,791行(4.7倍の誤差)。 さらに最も複雑な関数の上位8件が全て他人(Anthropic公式プラグイン)のコードで、marketplaces/とcache/に同一関数が二重計上されていた(CC=82 が2件)。
1-3. 除外が効いたことの検証(省略禁止)
除外を適用したら、除外前後の数値を並べて確認する。桁が変わったら除外が効いた証拠。効いていないのに気づかない事故を防ぐ。
⚠️ 実例:
find . -path ./plugins -prune -o -name 'test_*.py' -printの prune が効かず、 テストファイル 2,429件(実際は44件・55倍) と出たがエラーは一切出なかった。find -pruneは使わない。 Glob ツール / ripgrep の--glob '!dir'を使う。
Phase 2: 計測
# 言語別LOC・ディレクトリ別LOC・Python複雑度・カバレッジ所在
PYTHONIOENCODING=utf-8 python3 <skill>/scripts/repo_metrics.py <REPO> [除外dir...]
# テスト/ソースの分離(テストが src ツリーに混在していても正しく出る)
PYTHONIOENCODING=utf-8 python3 <skill>/scripts/split_tests.py <REPO> [除外dir...]
2-1. 複雑度の扱い(🔴 言語で精度が違うことを必ず明記)
| 言語 | 手段 | 報告時のラベル |
|---|---|---|
| Python | 同梱スクリプトの AST 解析 | 循環的複雑度(正確) |
| JS/TS | node_modules/acorn があれば AST。無ければ分岐キーワード密度で代用 |
「近似値」と明記・Python の CC と直接比較しない |
| Go / Rust / Java | gocyclo 等の既製ツールがあれば使用。無ければファイルLOCと分岐密度 |
「近似値」と明記 |
⚠️ 実例:
reserve-optimizer(JS 26,201行)で、Python の AST しか持たないスクリプトが 本体JSを一切測らず、デモ録画用の Python 1,310行だけを測って「最大CC=32」と報告した。 エラーは出なかった。対象言語のLOCと、実際に解析した関数数が桁で合っているかを必ず突き合わせる。
2-2. 複雑度は「率」と「最大値」の両方を見る
片方だけでは判断できない。
NexusCore : CC>20 が 16/1020 (1.6%) 最大CC=31
atelier : CC>20 が 51/3537 (1.4%) 最大CC=63 ← 率は同等だが最大値が2倍
2-3. テスト件数の数え方(言語・フレームワークで違う)
| 環境 | 数え方 |
|---|---|
| pytest | ^\s*def test_ |
| jest / vitest | it( / test( |
| 自作ランナー | assert 呼び出し数などで代用し、代用したことを明記 |
テストの所在は1箇所とは限らない。 tests/ だけ見て数えると過小評価する。
⚠️ 実例:
claude-configはtests/だけで168件だったが、実際は5箇所に分散して 448件(2.7倍)。
2-4. カバレッジ
既存レポート(coverage.xml / lcov.info / coverage.out)をパースし、生成日時を必ず報告する。
- バイナリの
.coverageしか無い場合 →coverage reportを試す。それも不可なら**「未計測」と明記** - レポートが無い場合 → 「カバレッジは測定手段自体が未整備」と書く。推測値は書かない
⚠️ 実例:
atelier-kyo-managerの.coverageは2.5ヶ月前のものだった。
2-5. LFS ファイルの検出
.gitattributes に LFS パターン(filter=lfs)があるか最初に確認する。ある場合:
LFSポインタファイル(130バイト程度のテキスト)を実ファイルと混ぜて LOC に含めない。
ポインタ実測は git lfs ls-files または対象拡張子ファイルのサイズ確認で行う。
⚠️ 実例:
atelier-kyo-managerは png 908件が LFS ポインタ化しており偽差分の温床になった。
Phase 2.5: 計測健全性チェック(🔴 新設・省略禁止・Phase 3 の前)
計測結果が「黙って間違っている」可能性を Phase 3 以降に進む前に検査する。3項目全部確認:
- 総LOC > 0 — 主要言語のLOCが0なら計測自体が失敗(除外過剰・パス違い)
- 解析失敗件数の確認 —
repo_metrics.py出力の「⚠️ 解析失敗: N件」。N>0 は未検証事項への記載が必須 (古いPythonで全ファイルSyntaxError→LOCは出るが関数0個報告、という最悪ケースが実在) - 種別判定の根拠と計測内容の一致 — Phase 0 の判定根拠とした言語のLOCと、実際に解析できた 関数数・ファイル数が桁で合っているかを突き合わせる
異常を検出したら残りの Phase を中断し、「計測不能の理由」を未検証事項として報告する。 測定不能を誠実に返す停止条件(MiniMax critical指摘・2026-08-17 レビュー)。
Phase 3: 実行系の検証(🔴 終了コードを信じない)
lint / 型チェック / テストを実走する。ただし:
失敗を成功と誤認する既知パターン
| 症状 | 見分け方 |
|---|---|
| UNC パスで npm/node が動かない | 出力に UNC パスはサポートされません / CMD.EXE / C:\Windows が出る。それでも exit 0 になる |
| ツール未インストール | command not found だが CI 上では通る等 |
| 権限拒否 | 実行自体がブロックされる |
判定は終了コードでなく出力本文で行う。 上記が出たら「未検証」として報告する。
⚠️ 実例:
npm testがCannot find module 'C:\Windows\tests\run-all.js'で失敗したのに exit 0 を返した。終了コードを信じていたら「テスト通過」と誤報告していた。
CI の実態確認(宣言との突き合わせ)
CI 設定を実際に読み、走っているジョブと対象ディレクトリを列挙する。README の主張と突き合わせる。
⚠️ 実例:
reserve-optimizerの CI は29行・単一ジョブでworking-directory: workerのみ。 本体の gas-project 14,894行と32テストファイルは push/PR で一度も実行されていなかった。
Phase 4: 分析6項目
- プロジェクト構造 — 構成の妥当性 / モジュール依存 / 命名 / 実行コードが何箇所に分散しているか
- コード品質 — 複雑度分布 / 保守性 / 重複コード
- テスト — 件数・比率・低カバレッジ領域 / 単体・統合・E2E の区別が実態として機能しているか
- アーキテクチャ — 層構造が守られているか(逆流・循環)/ スケーラビリティ / セキュリティ
- ドキュメント — README の記述と実体の一致 / docstring 品質
- 依存関係 — 適切性 / 未使用依存 / バージョン整合性 / 脆弱性
よくある実態(チェックリスト)
- テストは書かれているが CI で走っていない(5リポジトリ中3件で発生)
- テストマーカー/タグが定義だけされて実使用ゼロ
- 依存宣言に未使用パッケージ(削除提案には動的import確認と削除後スモークを条件に付ける)
- 言語バージョンが複数ファイルで食い違う
- README に存在しないディレクトリが書かれている
未使用依存の判定(誤判定しやすい)
静的検索だけを根拠にしない。
- 文字列リテラル内の import をヒットさせない(サンドボックス用テンプレート等)
- 動的ロード(
importlib/require(変数)/entry_points/ DI / リフレクション)の有無を先に調べる - 削除提案には必ず「削除後にフルテスト+起動スモーク必須」を条件として添える
- 依存削除の実行は本スキルでは行わない(提案のみ・実行は対象リポジトリ側のタスクとして切り出す。 本スキルはコードを変更しない大前提と整合)
Phase 5: 出力
- エグゼクティブサマリー(1〜2段落)+ 専門知識のない人向けの平易な要約を併記
- 強み Top5 — 各々に実測の根拠
- 改善領域 Top10 — 優先度順・各項目に
file:line(種別テーラリング: コンテンツ/運用スクリプト集と 判定した場合は、改善領域の評価軸を Phase 0 の種別評価軸へ差し替える——例: コンテンツなら 「検証ゲートの欠落」を、運用スクリプト集なら「再現手順の未文書化」を上位に置く) - 具体的推奨事項 — 実行可能なコマンド・変更箇所を含む。着手順序と所要時間の目安も
- メトリクス表 — 規模 / カバレッジ / 複雑度 / アーキテクチャ / 依存
- 未検証事項(省略禁止)— 実行できなかった計測・古いデータ・確認しきれなかった前提
未検証事項のフォーマット(4要素必須)
各項目に ①Phase番号 ②計測項目 ③失敗理由 ④次に実行すべきコマンド を必ず揃える。
(例: 「Phase 3 / テスト実行 / UNC パスで npm が起動せず exit 0 / wsl bash -c 'cd <repo> && npm test'」)
Top10 のソート規則
優先度(P1→P3)順・同一優先度内は影響行数(LOC・CC・対象関数数)の降順で並べる。
優先度基準
- P1 — 放置コストが継続発生(CI時間・脆弱性・誤った数値の対外公開)かつ機械的作業で解消可能
- P2 — 構造的負債(今は動くが変更コストを上げ続ける)
- P3 — 品質の実質(数値は良いが実効性に疑問)
環境上の注意(Windows Desktop + WSL の UNC 経由)
grep -r/findは2分でタイムアウトする。Grep ツール(ripgrep)/ Glob ツールを使う- cwd が UNC 配下だと絶対 UNC パスへの再
cdが二重解決で失敗する。既知の基点から相対で移動する - Python 出力が文字化けする →
PYTHONIOENCODING=utf-8を付ける ~/.claude/skills等が I/O エラーで読めないことがある。Path.exists()の False は 「無い」ではなく「読めない」かもしれない
WSL ネイティブでは不要(2026-08-17 実測検証済み)
WSL 側(/home/... 配下)では上記 UNC 起因の摩擦は発生しない。実測(zenn リポジトリ・2026-08-17):
| 摩擦点 | WSL ネイティブ実測 |
|---|---|
grep -r / find タイムアウト |
0.025s / 0.147s で完了(2分タイムアウトは UNC 起因) |
cd の二重解決失敗 |
絶対パス再 cd 正常動作 |
PYTHONIOENCODING なしの文字化け |
化けない(WSL ロケールが UTF-8 のため・付けても害はないので Windows 併用なら付けたまま) |
npm test の偽 exit 0 |
再現しない(MODULE_NOT_FOUND で exit 1 を返す・node v20 実測) |
⚠️ 例外: /mnt/c/... 配下のリポジトリを WSL から見る場合は Windows FS 経由の I/O 遅延が
残るため、上記 UNC 時代の注意が依然有効。UNC 特有の問題は「UNC パス(//wsl.localhost/... または
\\...)経由」か「/mnt/c 経由」かで発生条件が変わることに注意。
複数リポジトリを続けて見るとき
1リポジトリだけでは基準が持てない。 比率や閾値は横断で初めて意味を持つ。
test:src 比の実測レンジ(同一ユーザーの5リポジトリ)
NexusCore 3.10 / reserve-optimizer 0.74 / atelier 0.59 / claude-config 0.30 / zenn 0.15
→ 「0.59 は低い」とは言えない。種別と CI 実行有無をセットで見る
このレンジは参考値であって閾値ではない。 「0.15未満は赤」のような判定線として使わないこと。
横断で見たら、個々では見えない共通パターン(例:「テストは書くが CI に繋いでいない」)を必ず報告する。
トリガーワード
「リポジトリレビューして」「コード品質を評価して」「このプロジェクトを診断して」「包括レビュー」
「アーキテクチャ評価して」「技術的負債を洗い出して」/ /repo-review