0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitHub Copilot の従量課金移行に備える:リポジトリ構造による「プロンプトの選択的コンテキスト設計」

0
Posted at

はじめに

2026 年 6 月 1 日以降の GitHub Copilot は課金単位が「Premium Requests(回数)」から「GitHub AI Credits(トークン量)」に変わり、従来のように上限超過時に安いモデルへフォールバックする挙動もなくなります。この変化は、不要なコンテキストを読ませ続ける運用がコスト増につながりやすいことを意味します。

これまでの Copilot 活用は「いかに多くの情報を与えて賢くするか」という情報の足し算のフェーズでした。しかし、これからは「いかに最小のコンテキストで最大の精度を引き出すか」というコンテキストの引き算と、それを人間が意識せずに行える構造化が重要になります。

この記事では、場当たり的なプロンプト削りではなく、リポジトリの構造(applyToNever リスト)によって「必要な時だけ、必要な情報を、自動的に読み込ませる」設計手法について解説します。

項目 変更前 変更後(6 月 1 日〜)
課金単位 Premium Requests(回数) GitHub AI Credits(トークン量)
コード補完 無制限 変わらず無制限
上限超過時 安いモデルへフォールバック フォールバックなし(追加課金 or ブロック)
Business のクレジット 1,900 Credits / ユーザー / 月
Enterprise のクレジット 3,900 Credits / ユーザー / 月
プール管理 ユーザー個別 組織全体でプール共有
プラン月額 変わらない 変わらない

参考: https://dev.classmethod.jp/articles/shoma-github-copilot-pricing-major-revision-2026-june-1-premium-requests-to-github-ai-credits/

解決策は「分ける」ことではなく、「判断を構造に埋め込む」ことです。

この問題が厄介なのは、表面上は機能しているように見えるからです。.github/instructions/ にファイルを並べ、copilot-instructions.md に共通ルールを書けば、一応 Copilot は読んでくれます。しかし「一応読む」と「必要なときだけ正確に読む」の間には大きなギャップがあります。

そのギャップを埋めるのが コンテキスト設計 です。どのファイルをどのタイミングで読み込むかを、ファイルパスと applyTo と Never リストという3つの仕組みで構造的に決めます。人間が毎回判断するのではなく、リポジトリ側で判断を固定します。

この記事では、その設計の全体像を示します。原則・意思決定フロー・3層モデル・アンチパターン・チェックリストを含む形で、他のプロジェクトでそのまま再現できることを目標とします。

レポジトリ:

2. データから見る問題の本質:改善の正体は「品質/トークン比」

まず数字を見ましょう。同じタスク(Flask の /health エンドポイントのレビューと小規模リファクタリング)を3つの構成で比較します。ここでの値は、同一タスクに対する比較のための計測結果であり、厳密なベンチマークではありません。

シナリオ 戦略 入力 tokens 出力 tokens 合計
ベースライン A(指示なし) 1,032 600 1,632
既存構成 B(全読み込み) 8,884 600 9,484
既存構成 C(選択的読み込み) 2,289 600 2,889
最適化後 B(全読み込み) 9,428 600 10,028
最適化後 C(選択的読み込み) 3,487 600 4,087

ここで最初に確認すべき事実があります。最適化後の総トークン量は既存構成より多いです。全読み込みでは 544 tokens 増、選択的読み込みでは 1,198 tokens 増です。差分率にすると、それぞれ +6.1%、+52.4% の入力増をもたらします。

「改善したのにトークンが増えた」――これは一見矛盾に見えるかもしれませんが、設計上は十分ありえます。

品質スコアを並べると意味が明らかになります。

シナリオ 品質スコア(1〜5)
ベースライン A 2.0
既存構成 B 3.0
既存構成 C 4.0
最適化後 B 3.5
最適化後 C 4.5

最適化後 C(選択的読み込み)は、最も高い品質スコア(4.5/5)を記録しながら、既存構成 B(全読み込み)よりも大幅に少ない入力トークンで動作します。既存構成 B(9,484 tokens, 品質3.0)と比較すると、4,087 tokens で品質4.5を引き出しています。

これが「品質/トークン比」の改善です。絶対的なトークン量の削減を目指すのではなく、同じコストで得られる品質の密度を高めることを目的としています。

設計が正しく機能するとどうなるでしょうか。最適化後の選択的読み込みが既存構成の選択的読み込みより多くのトークンを消費するのは、Flask 固有の flask.instructions.md が追加されているためです。しかし、この追加によってタスクに必要な情報をより正確に渡せるようになり、結果として品質スコアが 4.0 から 4.5 へ向上しました。構造化のための追加トークンは、目的に対して妥当な投資(コスト)と言えます

では、なぜ最適化後の全読み込みは品質 3.5 に留まるのでしょうか。それは「正しく設計されたファイル群を、すべて一度に読んでしまう」からです。必要な情報と不要な情報が混ざると、Copilot の判断が分散します。選択的読み込みの品質が全読み込みを上回る理由はここにあります。

選択的読み込みの価値は、単なる量の節約ではなく、判断精度の向上にあります。

3. なぜ問題が起きるのか:構造分析

3-1. ファイルの存在 ≠ 読み込みタイミング

.github/instructions/flask.instructions.md というファイルが存在します。しかしそれだけでは、「Flask を触るときだけ読む」は保証されません。applyTo がなければ、このファイルをいつ読むかの判断は Copilot の推論に委ねられます。推論は会話の流れに依存します。つまり、毎回同じ結果になりません。

ファイルの存在と読み込みタイミングは別物です。この区別を設計に持ち込まないと、Selective load は「知識のある人が毎回手動で選ぶテクニック」に留まります。

3-2. 判断が人間依存になる構造

applyTo のない指示(instruction)ファイル群が並んでいると、「今日のタスクにはどのファイルを読ませるべきか」を人間が判断しなければならなくなります。この判断コストが蓄積すると、次第に「全部読ませておけば間違いない」というショートカット(全読み込み)が選ばれるようになります。全読み込み(Full load)は、いわば判断コストを避けるためのリスク回避の産物です。

設計上の問題を個人のスキルで補おうとすると、属人化を招きます。担当者が変われば判断基準が揺れ、Copilot のバージョンが上がれば挙動が変わります。構造ではなく個人の知識に依存した設計には、再現性がありません。

3-3. Never リストの不在

「何を読むか」だけを設計し、「何を読まないか」を明示しないと、デフォルト設定が「全読み込み」の状態に近づいていきます。

ISSUE_TEMPLATE/PULL_REQUEST_TEMPLATE/CODEOWNERSdependabot.ymlSECURITY.mdworkflows/ などのファイルはリポジトリ管理上は重要ですが、実装やレビューのタスクで毎回読み込む必要はありません。これらを「Never リスト」として明示的に除外していない設計では、不要なファイルを都度読み込んでしまう可能性を排除できません。

Never リストの欠如は、常に「全読み込み」へと引きずられる構造を生んでしまいます。

3-4. ファイルを分けただけでは構造にならない

instructions/ ディレクトリ配下にファイルを10個並べても、applyTo が設定されていなければ、それは構造ではなく単なる「ファイルの集まり」です。本来の構造とは、「誰が操作しても同じ判断が再現される仕組み」を指します。

ファイルを分けるという行為と、読み込みタイミングを仕組みとして組み込む行為は全く別物です。後者が伴わなければ、選択的読み込み(Selective load)は正しく機能しません。

4. コンテキスト設計:原則・フロー・3層モデル

4-1. 設計原則

原則1: 判断はリポジトリ構造に埋め込む

「このタスクには何を読ませるか」を毎回人間が考える設計は失敗します。判断がファイルのパス・名前・applyTo に紐付いていない限り、Selective load は「知識のある人だけが使えるテクニック」になります。構造に埋め込まれた判断は、チームが変わっても、Copilot のバージョンが変わっても、同じ結果を再現します。

原則2: 「読まないもの」を先に決める

「何を読ませるか」の設計より「何を読ませないか」の設計が先です。読み込み対象に明示的な除外リストがなければ、判断が曖昧なファイルはデフォルトで読まれます。Never リストがない設計は Full load へ引き寄せられる構造になります。

原則3: 1ファイル1責務。責務の境界は「出てはいけない単語」で定義する

flask.instructions.md に pytest の記述が混入した瞬間、テストタスクのときも Flask ルールを読む根拠が生まれます。責務境界は「何を書いてよいか」ではなく「何を書いてはいけないか」で引きます。除外ルールがなければ肥大化は止まりません。

原則4: ベースラインは軽さではなくトリガー密度で評価する

copilot-instructions.md を「薄く」する目的は文字数削減ではありません。「読み込みトリガーの情報密度を高く保ちながら、タスク固有のルールを一切持たない」ことです。トリガーが多くても、それが外部ファイルへの委譲であれば、ベースラインとして正しいです。

原則5: コスト評価は絶対量ではなく品質/トークン比で行う

Selective load の目標は「最小トークン」ではなく「このタスクに必要十分なコンテキストで最高品質を引き出すこと」です。構造化のための追加トークンは正当なコストです。評価すべきは削減量ではなく、同じコストで品質が再現できるかどうかです。

4-2. 意思決定フロー

「このファイルをどこに配置すべきか」を判断するためのフローです。設計者が不在でも、誰が判断しても同じ結論に達することを目指します。

新しいルール・指示・テンプレートを .github/ に追加したい
│
├─ Q1: 全ての Python ファイル編集タスクで、このルールは必要か?
│       AND タスクの種類が変わっても有効か?
│
│   YES ──► Q1a: applyTo なしで全セッションに効かせる必要がありますか?
│               YES ──► copilot-instructions.md に追加する
│                        ただし以下を満たすこと:
│                        - タスク固有の例を含まない
│                        - 具体的実装規約を含まない(外部ファイルへのトリガーのみ)
│                        - 追加後の copilot-instructions.md が 700 tokens を超えるなら
│                          その内容は Layer2 に移動する
│               NO  ──► Layer2 へ(Q2へ進む)
│
│   NO  ──► Q2: 特定のファイルパス(glob パターン)にバインドできますか?
│               例: src/api/**、tests/**、.github/workflows/**
│
│               YES ──► Q2a: 同じ責務を扱う instruction ファイルが既に存在するか?
│                           YES ──► 既存ファイルに追記する
│                                    ただし以下を確認:
│                                    - 追記後にそのファイルの責務が混在しないか
│                                    - 「出てはいけない単語チェック」を実施する
│                           NO  ──► .github/instructions/ に新規ファイルを作成する
│                                    - ファイル名: {役割}.instructions.md
│                                    - 先頭に applyTo: を必ず書く
│                                    - 責務外単語リストをコメントで書く
│
│               NO  ──► Q3: 人間が明示的に「今このタスクに使う」と判断して呼ぶものか?
│                           例: セキュリティレビュー、リリースノート生成、障害対応
│
│                           YES ──► Q3a: 手順・テンプレートの性質か?
│                                       手順 ──► .github/skills/ に置く
│                                       テンプレ ──► .github/prompts/ に置く
│
│                           NO  ──► .github/ に置かない
│                                    このファイルは会話コンテキストとして
│                                    設計されていない(docs/ や src/ に置く)

このフローの目的は「迷わず同じ判断を出すこと」です。設計者がいなくても、このフローを辿れば Layer1/Layer2/Layer3 のどれに属するかが一意に決まります。

「出てはいけない単語チェック」の実施方法

各 instruction ファイルを追加・編集した後に、以下の表で該当ファイルの列を確認してください。その単語が含まれていれば、責務が混在しています。

ファイル 出てはいけない単語・概念
python.instructions.md Blueprint、create_app、pytest、fixture、@app.route
flask.instructions.md pytest、fixture、assert、conftest、Terraform、workflow
testing.instructions.md Blueprint、create_app、jsonify、Flask、Makefile
architecture.instructions.md pytest 記法、型ヒント構文の詳細、CI/CD ステップ
infrastructure.instructions.md Flask、pytest、Blueprint、型ヒント
copilot-instructions.md 個別 API の規約、テストの命名規則、具体的な実装パターン

4-3. 3層モデル定義

Layer 1: Core(常時読み込み)

項目 内容
役割 全セッション・全タスクに共通する前提の固定
含めてよい内容 言語バージョン、型記法の統一(X | None など)、docstring スタイル、出力形式のルール、読み込みトリガーの委譲先(applyTo の宣言)、Never リスト
含めてはいけない内容 Flask・pytest・Terraform 固有のルール、具体的な実装パターン、サンプルコード、タスク固有の例、他ファイルに書いた内容の再掲
トークン目安 600〜800 tokens。超えたら Layer2 に移動を検討してください。
具体例 copilot-instructions.md: 型ヒント方針、docstring 書式、出力スタイル、context loading rules の宣言

Layer1 が肥大化するのは Layer2 の整備不足のサインです。Core に Flask ルールが混入しているなら、flask.instructions.mdapplyTo を設定すれば移動できます。Core に書き続ける必要があるかを問いましょう。

Layer 2: Task-specific(パスに応じた自動読み込み)

項目 内容
役割 タスク・ファイルパスに一対一対応したルールの自動適用
含めてよい内容 特定フレームワークの規約、テスト設計方針、アーキテクチャの判断基準、セキュリティ要件(条件付きで適用)
含めてはいけない内容 他の Layer2 ファイルと責務が重複するルール、Layer1 に書いた内容の再掲、On-demand で使うべき手順書・テンプレート
トークン目安 1ファイル 300〜500 tokens。「長くなった」と感じたら責務が混在している
具体例 flask.instructions.md(applyTo: src/api/**/*.py)、testing.instructions.md(applyTo: tests/**/*.py)、infrastructure.instructions.md(applyTo: .github/workflows/**

Layer2 ファイルの必須構造は以下の通りです。applyTo と責務外単語コメントの両方がなければ Layer2 として成立していない。

---
applyTo: "src/api/**/*.py"
---

# Flask 実装規約

<!-- 責務外単語: pytest, fixture, assert, conftest, Makefile, Terraform -->

(本文)

Layer 3: On-demand(明示的に呼ぶときだけ読む)

項目 内容
役割 頻度が低いが実行時に詳細な手順が必要なタスクの支援
含めてよい内容 ステップバイステップの手順、チェックリスト、タスク固有のテンプレート、ロールプレイ的な指示(エージェント用)
含めてはいけない内容 常時必要なルール(Layer1 に移動)、自動適用できます規約(Layer2 に移動)、実装上の判断基準
トークン目安 上限なし(必要に応じて詳細に書いてよい)。読まれる頻度が低いため総コストへの影響は小さい
具体例 skills/code-review-procedure/SKILL.mdprompts/security-review.prompt.mdprompts/release-notes-generation.prompt.md

4-4. アンチパターン

アンチパターン1: copilot-instructions.md に全部書く

なぜ起きるか

設計の初期段階では、単一ファイルに全部書くのが最も手軽です。Layer2 の仕組みを知らない、あるいは applyTo の設定が面倒という理由で Core に集積されます。

なぜダメか(構造的に)

Core は全セッションで読まれます。Flask ルール・pytest 規約・インフラ設定を全て Core に書くと、Terraform を触るタスクでも pytest 規約を読みます。セキュリティレビューをするタスクでも Blueprint の規約を読みます。どのタスクでも同じ重いコンテキストを運び続ける構造になります。Selective load が機能しません。

回避方法

Layer1 に書いた後で「このルールは特定のパスでのみ意味を持つか」を問う。Yes なら Layer2 に移動する。Core の肥大化は Layer2 ファイルの未整備のサインとして扱う。

アンチパターン2: applyTo なしの instruction ファイルを置く

なぜ起きるか

「分けた」という事実に満足してしまいます。ファイル名で役割を示しているから、Copilot が適切に使うだろうという期待を持ってしまいます。

なぜダメか(構造的に)

applyTo がなければ、そのファイルはいつ読まれるかが不定になります。Copilot がコンテキストとして選択するかどうかは、会話の流れと推論に依存します。毎回同じ結果になりません。Selective load の「再現性」は applyTo によるパスバインドが前提です。ファイルを分けただけでは構造になりません。

回避方法

instructions/ に置くファイルには必ず applyTo を書くことをルール化します。applyTo が書けないファイルは Layer2 ではなく Layer3(prompts/skills/)に置きます。

アンチパターン3: 同じルールを複数ファイルに重複させる

なぜ起きるか

レビュー観点を instructions/ にも prompts/ にも skills/ にも書いた方が確実だと考える。安心のための重複、または過去のバージョンが残った状態で新ファイルを追加することで起きる。

なぜダメか(構造的に)

Selective load で3ファイルそれぞれを選んだとき、同じルールが3回読まれます。重複トークンは純粋な無駄です。さらに深刻なのは、微妙に文言が異なる場合です。Copilot は「どちらが優先されますか」を判断できません。出力が揺れる原因になります。

回避方法

ルールを書く前に「このルールはすでにどこかに書いてありますか」を確認します。Layer1 に書いたルールは Layer2 で再掲しません(参照もしません)。

アンチパターン4: Never リストを持たない

なぜ起きるか

「読まないもの」は意識しないと設計に含まれません。「必要なものだけ読む」と言いながら、「不要なものを明示しない」設計は Not-Never のデフォルトになります。

なぜダメか(構造的に)

Never リストがなければ、判断が曖昧なファイルはその都度読まれる可能性があります。ISSUE_TEMPLATE/workflows/SECURITY.md はリポジトリ管理として重要ですが、実装・レビュータスクで毎回読む必要はありません。これらを明示的に除外しない設計は、Full load への引力を持ち続けます。

回避方法

copilot-instructions.md の中に Never セクションを作り、「原則として読まないファイル・ディレクトリ」のリストを持ちます。新しいファイルを追加するたびに Never/Layer2/Layer3 のどれかに分類します。

5. .github 設計への落とし込み

5-1. copilot-instructions.md の役割

copilot-instructions.md は全セッションで読まれる唯一のファイルです。だからこそ、ここに何を書くかが設計全体の品質を決めます。

このファイルに書くべきことは3つだけです。

  1. リポジトリの技術前提(言語・バージョン・スタック)
  2. 出力スタイルの固定(変更箇所のみ・前置きなし・不明点は確認など)
  3. 読み込みトリガーの宣言(どのパスでどのファイルを自動適用するかの地図)

ここに書いてはいけないのは、タスク固有の実装ルールです。Flask の Blueprint 設計方針も、pytest のフィクスチャ命名規則も、copilot-instructions.md に書く必要はありません。それらは Layer2 に委譲し、Core はトリガーの宣言だけを持ちます。

copilot-instructions.md の構造例

# GitHub Copilot の指示

## プロジェクト: REST API (Python 3.12 + Flask)

技術: Python 3.12 | Flask 3.x | pytest | ruff

## 型注釈とドキュメント

- すべての関数に型ヒントを必須とする
- `Optional` ではなく `X | None` を使用する
- 組み込みジェネリクスを使用する: `list[str]`, `dict[str, int]`
- Google スタイルのドックストリング: Args / Returns / Raises

## 応答スタイル

- 変更された部分のみを出力する(全文書き換えは行わない)
- 説明よりコードを優先する
- 前置きは書かない
- 不明点があれば確認する
- ファイルパスをコードブロックに含める

## コンテキスト読み込みルール

### Auto-load

- `**/*.py` を読む・編集するときは `python.instructions.md`
- `src/api/*.py``src/api/**/*.py` を読む・編集するときは `flask.instructions.md`
- `tests/**/*.py` を読む・編集するときは `testing.instructions.md`

### Never

- 無関係な `.github/workflows/**`
- 無関係な `.github/ISSUE_TEMPLATE/**`
- 無関係な `.github/PULL_REQUEST_TEMPLATE/**`
- `docs/old/`

このファイルが700 tokens を超えてきたら、それは Layer2 ファイルの設定不足を意味します。超えた内容を Layer2 に移す前に、そのルールが「どのパスにバインドできるか」を問いましょう。

5-2. instructions/ の分離戦略

instructions/ の設計で最も重要なのは、ファイルを分けることではなく「どの粒度で分けるか」を決めることです。

粒度の基準は「タスクが変わったとき、読むファイルのセットが変わるか」です。テストを書くときと Flask の実装を書くときで、異なる instruction が読まれるなら、その分離は正しいです。同じタスクで常に一緒に読まれるなら、分ける必要はありません。

このリポジトリでの分離例

ファイル applyTo 役割
python.instructions.md **/*.py 型ヒント、docstring、インポート順、例外設計
flask.instructions.md src/api/**/*.py Blueprint、create_app、JSON レスポンス、HTTPException
testing.instructions.md tests/**/*.py pytest 命名、fixture、アサーション分割、カバレッジ
architecture.instructions.md —(条件付き) Blueprint 配置、責務分離、dependency injection
infrastructure.instructions.md .github/workflows/**, Makefile CI/CD ジョブ設計、Terraform 命名
security.instructions.md —(条件付き) 認証、認可、secret 管理、入力検証

architecture.instructions.mdsecurity.instructions.mdapplyTo を持ちません。それは「特定のパスにバインドできない」からではなく、「人間が明示的に「今このタスクに使う」と判断して呼ぶもの」だからです。条件付きで読む設計は、意思決定フローの Q3 に該当します。

5-3. ディレクトリ構成の全体像

.github/
├── copilot-instructions.md          # Layer 1: 全セッションで読む
│
├── instructions/                    # Layer 2: パスに応じて自動読み込み
│   ├── python.instructions.md       # applyTo: **/*.py
│   ├── flask.instructions.md        # applyTo: src/api/**/*.py
│   ├── testing.instructions.md      # applyTo: tests/**/*.py
│   ├── architecture.instructions.md # 条件付き(Conditional)
│   ├── infrastructure.instructions.md # applyTo: .github/workflows/**, Makefile
│   └── security.instructions.md     # 条件付き(Conditional)
│
├── prompts/                         # Layer 3: 明示的に呼ぶとき
│   ├── security-review.prompt.md
│   └── release-notes-generation.prompt.md
│
├── skills/                          # Layer 3: 明示的に呼ぶとき
│   ├── code-review-procedure/
│   │   └── SKILL.md
│   └── incident-response/
│       └── SKILL.md
│
├── agents/                          # Layer 3: 専任エージェント
│   └── code-review-specialist.agent.md
│
│ # ── Never ──────────────────────────────────────────────────
├── workflows/                       # 原則として会話コンテキストには読まない
├── ISSUE_TEMPLATE/                  # 同上
├── PULL_REQUEST_TEMPLATE/           # 同上
├── CODEOWNERS                       # 同上
├── dependabot.yml                   # 同上
└── SECURITY.md                      # 同上

この構成が示しているのは「ファイルの置き場所の決め方」です。置き場所が決まれば、読み込みタイミングが決まる。読み込みタイミングが決まれば、Selective load が機能する。

6. プロンプト設計との接続

6-1. なぜプロンプトを分けるのか

プロンプトを分ける目的は、コンテキストの最適化です。調査・実装・レビューは、それぞれ必要とするコンテキストが異なります。1つのプロンプトで全部やろうとすると、途中で必要な文脈が変わり、全体のコンテキストが膨らみます。

調査フェーズで必要なのは「何がどこにあるか」です。実装フェーズで必要なのは「どのルールに従って書くか」です。レビューフェーズで必要なのは「変更が意図と整合しているか」です。3つのフェーズを1つのプロンプトに詰め込むと、Copilot はどのフェーズの判断を優先すべきかを決めきれなくなります。

6-2. 調査 / 実装 / レビューの分離

調査プロンプト

目的: 対象範囲と現状を把握する。何が変更候補かを絞り込む。

対象: `src/api/endpoints/health.py``tests/test_health.py`

確認したいこと:

- 実装とテストの整合
- Blueprint の責務分離が正しいか
- 型ヒントが全関数に付いているか

読まないもの: `.github/workflows/**``docs/``ISSUE_TEMPLATE/**`

出力: 問題があれば箇条書きで。なければ「問題なし」だけ返す。

実装プロンプト

目的: 調査で特定した問題を修正する。変更範囲を最小にする。

前のレビューで `health()` 関数に docstring が不完全との指摘があった。

修正対象: `src/api/endpoints/health.py` のみ

制約:

- Google スタイルの docstring に修正する
- 型ヒントは変更しない
- 関数シグネチャは変更しない

出力: 変更箇所のみ。ファイルパスを先頭に書く。

レビュープロンプト

目的: 変更が設計意図と整合しているかを確認する。

変更済み: `src/api/endpoints/health.py`

確認観点:

- `testing.instructions.md` の命名規則に沿っているか
- `flask.instructions.md` のレスポンス形式に合っているか
- 他のエンドポイントと整合性がありますか

出力: OK / NG と理由を1〜2行で。

6-3. コンテキスト最適化との関係

調査プロンプトは「読むファイルの地図」を持ちます。実装プロンプトは「適用するルールの指定」を持ちます。レビュープロンプトは「判断基準の参照先」を持ちます。

このように分割することで、各フェーズで必要な instruction だけを読み込めます。調査フェーズで testing.instructions.md を読む必要はありません。実装フェーズで security.instructions.md を読む必要はありません(セキュリティ関連の変更でなければ)。

プロンプトの分割は、Layer2 の分離と連動します。Layer2 が正しく設計されていると、プロンプトは「このタスクで使う instruction を選ぶ」という判断をしなくて済みます。applyTo が自動的に選んでくれるからです。

逆に言うと、プロンプトの中で「今回は〇〇を読んでください」と毎回書かなければならないなら、それは Layer2 の applyTo が機能していないサインです。

6-4. On-demand プロンプトと Layer3 の位置づけ

prompts/skills/ は Layer3 として「明示的に呼ぶときだけ読む」設計です。

prompts/security-review.prompt.md はセキュリティレビューを実施するときだけ使います。skills/code-review-procedure/SKILL.md はコードレビューを形式的に行うときだけ使います。これらを毎回のコンテキストに含めると、普通の実装タスクでもセキュリティレビューの手順が混入します。

Layer3 が有効に機能するのは「このファイルをいつ使うかが明確なとき」です。使う人・使う場面・使い方が明文化されていない Layer3 ファイルは、ただのノイズになります。

実際の運用では、Layer3 ファイルを呼ぶ判断は人間が行います。そのための判断基準を copilot-instructions.md の Conditional セクションに記述しておくと、判断の再現性が上がります。

### Conditional

- セキュリティ関連のキーワードや変更があるときだけ `security.instructions.md` を読む
- アーキテクチャ、Blueprint 配置、モジュール分割に触れるときだけ `architecture.instructions.md` を読む

7. まとめ:設計の品質とは「再現性」のことです

7-1. 「何を読ませるか」ではなく「何を読ませないか」

設計のゴールを「Copilot に必要な情報をすべて読ませること」に置いてしまうと、どうしても全読み込みへと傾いてしまいます。必要なものを漏れなくリストアップするよりも、不要なものをあらかじめ除外する方が、設計としての安定性は高まります。

除外リスト(Never リスト)は、設計における「自律的な判断機能」です。新しいファイルを .github ディレクトリに追加するたびに、「これは会話の文脈に含めるべきか」を自問し、不要であれば即座に Never リストへ追加します。この習慣を徹底しなければ、リポジトリの成長に伴って全読み込みのコストは膨らみ続けてしまいます。

7-2. 選択的読み込みの再現性 = 設計の品質

選択的読み込みが正しく機能しているかどうかは、「設計者本人でなくても、同じタスクに対して同じファイルセットが読み込まれるか」という一点で判定できます。

これが実現できていれば、設計は成功です。もし結果がばらつくのであれば、判断が依然として人間に委ねられている証拠です。applyTo の設定漏れ、Never リストの更新忘れ、あるいは意思決定フローが無視されている可能性があります。

今回の実測値を見ると、最適化後の選択的読み込みはベースラインの約2.5倍のトークンを使用していますが、品質スコアは2倍以上(2.0 → 4.5)に向上しています。「品質/トークン比」で見れば、これが最も効率的な構成です。そしてこの高効率な状態は、applyTo、Never リスト、意思決定フローが正しく整備されていれば、誰でも再現可能です。

7-3. 他プロジェクトへの展開

この設計思想は Flask や pytest に限定されるものではありません。Layer 1(Core)の内容は、プログラミング言語やフレームワークが変わってもそのまま通用します。Layer 2 の flask.instructions.mddjango.instructions.md に入れ替え、testing.instructions.md を Jest 向けに書き換えるだけで、異なる技術スタックのプロジェクトにも即座に適用できます。

汎用性の指標は、「このチェックリストを受け取った第三者が、設計者の意図を汲み取らずとも同じ構造を再現できるか」にあります。意思決定フロー、チェックリスト、除外キーワード設定が揃っていれば、属人的な知識に頼ることなく、質の高いコンテキスト設計を維持できるのです。


優れた選択的読み込みの設計は、次の3要素を同時に満たします。

  1. 常に同じタスクで同じファイルセットが読み込まれる(再現性)
  2. タスクに必要十分なコンテキストで最高品質の結果を得られる(効率性)
  3. 設計者が変わっても同じ構造を維持・再構築できる(汎用性)

これらが揃うことで、「選択的読み込みを、迷わず実行できる状態」が整います。それこそが、コンテキスト設計の果たすべき役割です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?