TL;DR
- SDLC の各フェーズに 専門 SKILL(BA / Sec / Perf / Arch / DBA / QA / Ops / Compliance) を立てて多層レビューさせる構想は、図に描くと美しい。だが SKILLS を増やすだけでは成果物の粒度は上がらない。
- 効くようにするには SKILLS の手前に Grounding × 決定論判定 × 実行ループ の 3 つを整える必要がある。
- 本記事は前半でその 3 原則を一般論として説明し、後半に 筆者の自作 OSS への組み込み例 を事例として置く構成にしている。
- 結論: SKILL を増やすのは最後でいい。それより手前にやるべき投資がある。
はじめに: SKILLS を増やせば品質は上がる、という幻想
LLM を SDLC(ソフトウェア開発ライフサイクル)の各フェーズに組み込み、要件 → 設計 → 実装 → テスト → リリースの各段階で複数の専門 SKILL にレビューさせる、という構想が最近よく語られる。
絵としては魅力的だ。各観点の専門 SKILL が PR にコメントを残し、「すべての関門を通過したものだけがリリースされる」という多層ガードの世界観。
ところがこれを素直に組むと、LLM が自信ありげに承認した PR が、実際にデプロイすると壊れているという事故が普通に起きる。原因はだいたい次のどれかだ。
- Grounding が足りない: 顧客固有の制約・社内標準・過去事例を渡していないので、SKILL が「一般論として正しいが現場と合わない」提案をする
- 判定が LLM 主観: Pass/Fail を LLM に決めさせているので、LLM が「適切と判断します」と書けば通ってしまう
- 実行されていない: 静的レビューだけで判定しており、動かしてみないと分からない問題を取りこぼす
SKILLS を増やすのはこの 3 つを整えた後でいい。 整える前に SKILLS だけ厚くすると、自信ある誤りを大量生産する装置が出来上がる。
以下、3 つの投資をそれぞれ見ていく。
原則 1: Grounding 基盤を厚くする
SKILL が現場に合わない提案をしてくるのは、SKILL が悪いのではなく、現場の情報を渡していないから。
LLM は与えられたコンテキストの範囲でしか考えられない。「既存資産があるか」「社内ルールはどうか」「過去に似た案件で何を決めたか」を渡さなければ、SKILL は毎回ゼロベースで一般論を返してくる。
Grounding として渡すべき情報は大きく 3 種類ある。
(a) 過去案件の判断ログ
過去案件で「どの論点で」「どう判断したか」「なぜそう判断したか」を構造化して蓄積し、類似案件で参照できるようにする。
# 蓄積される 1 案件分の例
case_id: 2025-q4-fintech-api
industry: financial
pattern: serverless-api
decisions:
- point: storage_encryption
chosen: cmk
rationale: PCI DSS scope, BYOK 要件
- point: backup_dr
chosen: cross_region_warm
rationale: RTO 1h
embedding して類似検索できるようにしておけば、SKILL レビュー時に「業種 × パターンで過去どう決めたか」を渡せる。SKILL は一般論ではなく「自社の過去判断との整合」を語れるようになる。
(b) 顧客固有コンテキスト
ヒアリングや要件定義の段階で、既存資産プロフィールを構造化入力として取る。
| 項目 | なぜ必要か |
|---|---|
| 既存インフラ | 既存と整合しない提案を防ぐ |
| アカウント / 組織構成 | 全社統制と矛盾する提案を防ぐ |
| ID 基盤 | 既存認証と分断された提案を防ぐ |
| 監視・運用基盤 | 既存運用に乗らない提案を防ぐ |
| ハード制約 | 予算超過・禁止技術の提案を防ぐ |
| 過去インシデント | 同じ失敗を繰り返さない |
これが無いまま SKILL を増やしても、SKILL が増えた分だけ「一般論として正しいが現場と合わない指摘」が増えるだけだ。
(c) 組織ナレッジ(社内標準・命名規則・運用基準)
社内ルールを YAML 等で構造化して持ち、LLM プロンプトの冒頭に dump する。
naming:
pattern: "{env}-{service}-{resource}-{seq}"
tagging:
required: [CostCenter, Owner, Environment, DataClass]
monitoring:
forward_to: <社内標準ツール>
これを冒頭に置くだけで、LLM が「勝手にベストプラクティスを発明する」現象が大幅に減る。SKILL のレビュー指摘も「ベストプラクティス的にはこう」ではなく「社内標準ではこう」という具体性を持つようになる。
原則 2: 判定を機械可読にする
SKILL は「指摘の生成」「違反の意味を自然言語で説明」「リファクタ提案」にだけ使う。Pass/Fail を決めるのは LLM ではなく機械にする。
LLM SKILL に「セキュリティ的に問題ありません」と書かせて Pass にする運用は、構造的に壊れる。LLM は説得力のある文章を書くのが得意なので、間違っていても通ってしまう。
判定は決定論的なツールに任せる。
| 領域 | NG: LLM 主観判定 | OK: 機械判定 |
|---|---|---|
| セキュリティ | 「設定は適切と判断」 | 静的解析ツールの違反 0 |
| 最小権限 | 「ポリシー妥当」 | 権限解析ツールの Finding が 0 |
| コスト | 「コストは妥当」 | 見積もりツールが予算上限内 |
| 命名 | 「命名 OK」 | regex ルール pass |
| 依存 | 「ライブラリ問題なし」 | 脆弱性スキャナで High 以上 0 |
そのうえで、各成果物パターンが「通過すべき機械チェック」を自己定義する形にする。
# パターンごとの通過条件(例)
acceptance_criteria:
static_analysis:
required_pass: [rule-A, rule-B, rule-C]
cost:
max_monthly_usd: 200
integration_tests:
- happy_path
- cold_start_under_3s
- auth_denies_unauthorized
LLM はこれを満たすコードを生成し、CI がこれを判定する、という分業になる。
ゲートの Pass/Fail は CI に移譲する:
.github/workflows/
├── gate-2-design.yml # 設計書 lint, schema 検証
├── gate-3-implementation.yml # 静的解析, lint, 型チェック
├── gate-4-test.yml # integ test, contract test
└── gate-5-release.yml # drift check, approval required
LLM SKILL は PR コメントで指摘を残す役割。「通す/通さない」は CI の deterministic な結果。これだけで「LLM の心象次第で品質が変わる」現象が消える。
原則 3: サンドボックス実行ループを組む
静的レビューでは捕まらない実行時の問題を本番前に拾う仕組み。
静的解析や LLM レビューは「コードを読んで分かること」しか拾えない。一方で、現実のシステムで起きる問題の多くは「動かしてみないと分からない」: 実効権限、レイテンシ、初期化順序、依存サービスとの結合、etc.
使い捨て環境への自動 deploy
PR 単位で使い捨ての検証環境を払い出し、自動デプロイ → 検証 → 破棄する。
# CI 設定の概形
on: pull_request
jobs:
ephemeral-deploy:
steps:
- run: 環境を払い出す
- run: デプロイする
- run: 静的解析を実行
- run: 統合テストを実行
- run: コスト見積もりを取得
- if: always()
run: 環境を破棄
これで「実環境で初めて分かる問題」が PR の段階で表面化する。
実行結果を Grounding に戻す
サンドボックス実行で発生したエラー・警告を新規の判断ポイントとして記録し、原則 1 (a) の判断ログに蓄積する。
# 自動追記される例
runtime_findings:
- source: static_analysis
rule: least-privilege-5
status: deferred # 人間レビュー待ち
suggested_action: "Action を限定列挙へ"
- source: integ-test
test: cold_start_under_3s
result: failed
actual_ms: 4200
これにより「実環境で実際に何が起きたか」が判断ログに蓄積され、次案件の SKILL レビューに渡される(原則 1 (a) に戻る)。
Grounding → 判定 → 実行 → Grounding のループが閉じる。これが回り始めて初めて、システムは「案件をこなすたびに賢くなる」ようになる。
人間レビューはどこに置くか
全ゲートに人を置かない。置くべきところに置く。
3 原則を整えた上で、人間レビューの配置を決める。
| ゲート | 主判定 | 人間レビュー |
|---|---|---|
| ゲート 1: 要件 | LLM (SKILL) + 顧客レビュー | 必須(前提誤りを潰す) |
| ゲート 2: 設計 | SKILL 多角 + 過去案件 RAG | 推奨(不可逆判断の合意) |
| ゲート 3: 実装 | 機械判定 | 不要(差分レビューのみ) |
| ゲート 4: テスト | 機械判定 | 不要 |
| ゲート 5: リリース | 機械判定 + 承認権限 | 必須(本番投入は不可逆) |
設計の肝:
- 人間レビューの密度は 判断の不可逆性に比例させる
- ゲート 3-4 は機械判定のみで通せる設計にし、人間はそこに介在させない(さもないと人間がボトルネックになる)
- ただしゲート 1 と 5 は絶対に省略しない
ゲート 1 を省略すると「上流誤りを下流で合理化する」事故が起きる。要件の誤認を SKILL が引き継いだまま設計・実装・テストを通過させ、リリース直前に「そもそも要件が違っていた」と気づくパターンだ。多層 SKILL レビューは上流誤りを発見する仕組みではない(SKILL は与えられた前提の中で最適化する)。だから上流に人を置く。
ゲート 5 を省略すると、機械判定をすべてパスしたコードがそのまま本番に出る。機械判定は「ルール違反していない」ことしか保証しない。「今このタイミングで本番に出していいか」を判断するのは依然として人間の仕事だ。
実装フェーズ(現実的なロードマップ)
Phase A: Grounding 入力拡張
├ 既存資産スキーマ
├ 組織ナレッジ
└ 過去判断ログの蓄積基盤
Phase B: 機械判定の組み込み
├ パターン定義に通過条件
├ 静的解析 / 見積もり / 権限解析の CI 連携
└ ゲート判定の CI 移譲
Phase C: サンドボックス実行ループ
├ 使い捨て環境の払い出し
├ 統合テストハーネス
└ 判断ログへの自動フィードバック
Phase D (継続): SKILLS の厚み増 ← ここで初めて意味が出る
├ ロール別 SKILL の整備
└ オーケストレーター LLM の判断ルール
Phase D を最後に置いているのが本記事の主張です。 Grounding と決定論判定と実行ループが無い状態で SKILL を増やすのは、自信ある誤りを大量生産する装置を作ることになる。
まとめ
SKILLS を増やす前に Grounding × 決定論判定 × 実行ループを整えよ
- Grounding: 過去判断・既存資産・組織ナレッジを SKILL に渡す
- 決定論判定: Pass/Fail は LLM ではなくツールに決めさせる
- 実行ループ: 使い捨て環境で動かし、結果を判断ログに戻す
- SKILLS 整備: ここに来てようやく多層 SKILL を厚くする意味が出る
これが揃って初めて、図の世界観「LLM 多層レビューで品質・セキュリティ・信頼性を確保し、すべての関門を通過したプロジェクトのみリリース」が機能する形で動くようになる、というのが現時点の結論です。
SKILL を増やしたくなる気持ちはよく分かる(絵としても分かりやすいし、進捗としても分かりやすい)。だが「絵としての分かりやすさ」と「システムとして効くかどうか」は別の話だ、というのが筆者が回り道して得た教訓です。
