アーキテクチャ深掘り
§1でL0→L1→L2の「何がどこからどこへ流れるか」を扱ったのに対し、この節ではその流れが実際にどのように実装されているかを掘り下げる — ファイルがそのままコピーされずに再生成される理由、継承フロントマターが解釈される順序、ボイラープレート・ティア戦略が実践でどのように適用されるかの具体例、そしてプラットフォームディレクトリ(.claude/.gemini/.agents/.codex)が構造的にずれないよう保たれる方法までを扱う。
- L2ファイルがL1をそのままコピーせず「再生成」される理由(Layout Reconstruction)
extendsフロントマターが実際に解釈される順序- LOCKED/MERGE/PRESERVE分類を実際のファイルに適用した例
- 3ティア戦略 — High/Medium/Lowの定義、frontmatter例、Tier Adjustment Rules、Tier Ceiling Rule
.claude/・.gemini/・.agents/・.codex/のプラットフォームパリティが強制される仕組み- 実行計画テンプレート — Design Gate(Row 0)、例外カテゴリ(E1〜E5)、実践例
Layout Reconstruction — L2がL1をそのままコピーしない理由
§1で簡単に触れたagents/pm.mdの事例をもう少し掘り下げてみよう。L0のagents/pm.mdはワークスペース全体のガバナンスを含んでおり、300行を超える。ここにはAuto-Modeの動作やライフサイクル状態フィールドのような、ワークスペースルートでのみ意味を持つセクションが混在している。L1のtemplates/common/agents/pm.mdがこれをそのままコピーすると、variant(バリアント)を新規作成するたびにプロジェクトとは無関係なワークスペース専用の内容まで一緒についてきてしまう。
そのためL1はコピーの代わりにフィルタリングされた再構成を行う — L0の原本からvariantのスキャフォールディングに実際に必要なセクションだけを選び出し、ワークスペース専用セクションを除去したうえでextends参照によって残りをつなぐ。L2に降りる際も同じ原理が繰り返される。variant固有のオーバーライド(例えばco-retailであればマーケティングドメイン特化のPMルール)をL1の上に載せて最初から作り直すのであり、L1ファイルをdiff-patch方式で修正するわけではない。その結果、L0のpm.mdが300行を超えていても、L2のpm.mdは50〜100行程度に保たれる — 「コピーして余分を削る」方式ではなく「必要なものだけを選んで新たに作る」方式だからである。
この設計が重要な理由は失敗モードにある。もしL1→L2が単純なコピーだったなら、L0でワークスペース専用セクションを1つ追加するたびにすべてのL3プロジェクトのpm.mdが不必要に膨れ上がる。Layout Reconstructionは「L0が知っていること」と「L2が知る必要があること」の間に常にフィルターを置くことで、この問題を根本から遮断している。
extends フロントマター — 継承が解釈される順序
extends: ../../../agents/pm.mdのようなフロントマターフィールドは「このファイルはあのファイルを参照する」という宣言であり、ファイルを統合するマクロではない。解釈順序は次の通りである。
- ツールがファイルを読み込む際(例えばClaude Codeが
agents/pm.mdを読み込む際)、まずfrontmatterのextendsパスを確認する。 - 参照された原本(L0またはL1)を読み込んで本文を継承するが、現在のファイルに明示的に再記述されたセクションがあれば、そのセクションのみをオーバーライドする。
- 原本にはなく現在のファイルにのみ存在するセクション(例:variant固有のルール)はそのまま追加される。
つまりextendsは「継承+選択的オーバーライド+追加」の3段階で解釈されるのであり、2つのファイルをテキストとして繋ぎ合わせるものではない。この構造のおかげで、L1のtemplates/common/agents/pm.mdは実質的な内容をほとんど持たなくても(大部分はextendsでL0を指すのみ)有効なファイルとして機能し、L0で共通ルールが変更されればextendsを使うすべての下位ファイルが次回参照時に自動的に最新内容を反映する — ただし、これは「読み込み時に解釈される」ものであり、§1で扱った「ファイル同期(SYNC_IF_NEWER)」とは異なる仕組みである。extendsはツールがファイルを開く瞬間のリアルタイム参照であり、SYNC_IF_NEWERはupgrade-project.tsを実行して初めて更新される静的なファイルコピーである。両者は同じ「継承のように見える動作」をするが、更新タイミングが異なる点を混同してはならない。
ボイラープレート戦略の実例
§1で扱ったLOCKED/MERGE/PRESERVE分類が実際のファイルにどのように適用されるかを1つずつ例で確認してみよう。
- LOCKEDの例 —
.githooks/pre-commit:このファイルはシークレットスキャンやコミットメッセージ検証といったセキュリティゲートを実行する。プロジェクトごとにこの検証を変えてしまうと組織全体のセキュリティ基準がプロジェクトごとに異なってしまうため、upgrade-project.tsはローカルの修正有無にかかわらず、このファイルを常にL1最新版で上書きする。 - MERGEの例 —
CLAUDE.md:このファイルには<!-- WORKSPACE-MANAGED -->...<!-- /WORKSPACE-MANAGED -->で囲まれた区間(例:PMゲートウェイルール)と、その外側のプロジェクト固有ルール(例:「このプロジェクトは常に韓国語でコミットメッセージを書く」)が共存している。アップグレード時にはマーカーの内側だけがL1最新版に置き換えられ、マーカー外側の韓国語コミットルールはそのまま残る。 - PRESERVEの例 —
docs/context.md:このファイルはプロジェクトが何であるかを説明する文書であるため、L1は存在確認のみを行い、内容には一切関与しない。
3つの例を並べて見ると分類基準が明確になる — 変更されるとセキュリティ・ガバナンス事故につながるか(LOCKED)、組織ルールとプロジェクトの文脈が1つのファイル内で共存すべきか(MERGE)、プロジェクトのアイデンティティそのものか(PRESERVE)。この3つの問いを順に投げかけてみれば、この分類はほとんどすぐに判断できる。
3ティア戦略の深掘り — コスト最適化を実行時に適用する
第7章で紹介したtier割り当てはagents/*.mdのfrontmatterに静的に定義される。各エージェントファイルのtierフィールドはプラットフォームごとのモデルエイリアスに変換され、実行時に適用される。
frontmatter例
--- name: pm # pm, code-writer, automation-engineer ... tier: # プラットフォームごとのモデルエイリアス(実行時に変換される) claude: high # high = claude-opus-5-5 antigravity: high # high = gemini-3.1-pro codex: high # high = gpt-5.6-sol ---
この変換はmodel: inheritの裏で自動的に行われるため、agents/*.mdを書く人は具体的なモデル名をまったく知らなくてよく、「この役割がどれほど重い判断を行うか」だけを気にすればよい。
ティアの定義とモデルマッピング
| ティア | 目的 | Claude系の例 | Antigravity系の例 | Codex系の例 |
|---|---|---|---|---|
| High | 複雑な推論、アーキテクチャ設計、計画立案 | claude-opus-5-5 | gemini-3.1-pro | gpt-5.6-sol |
| Medium | コードレビュー、テスト、PRレビュー、品質ゲート | claude-sonnet-5-5 | gemini-3.8-flash | gpt-5.6-terra |
| Low | 高速で反復的なコーディング、スクリプト保守 | claude-haiku-5-5 | gemini-3.8-flash | gpt-5.6-luna |
この静的な割り当てが基準線(ベースライン)となるが、実際の実行時にはPMがTier Adjustment Rulesを適用して動的にコストを最適化する。基準線がhighのエージェント(architect)は複雑な設計判断を下す必要があるため、最も強力なモデルが必要となる。一方automation-engineerはADR-0036に基づく定型化されたスクリプトを書く役割であるため、lowティアで十分である — 「重い判断」が必要かどうかだけを見ればよいためだ。
Tier Adjustment Rules — 実行時のコスト最適化
PMが実行計画を立てる際、基準線から外れるティア調整が可能である。ルールは単純だ。
- ダウングレードは許可される — PMは単純な作業の場合、エージェントのティアを基準線より下げることができる。例えば基準線がmediumのdocs-writerが「README.mdの誤字を1つ修正する」作業を受けた場合、lowに下げてコストを削減できる。
- アップグレードは禁止される — 逆に基準線より高いティアに上げることは常に禁止される。lowのautomation-engineerをhighに上げて複雑なアーキテクチャを設計させることはガバナンス違反である。
- 失敗時の復元 — ダウングレードした作業が失敗した場合、PMは必ず該当エージェントの基準線ティアを復元して再試行しなければならない。
このルールの核心は「エージェント役割の複雑度の上限は固定だが、下限は状況に応じて調整できる」という原則である。PMはコスト削減のためにlowに下げることができるが、その作業がlowの能力を超えれば直ちに基準線に戻る。コストへの影響は第6章 §2-A P-2の実習で体感的に確認できる。
Tier Ceiling Rule
PMゲートウェイワークフロー文書(docs/governance/agents/pm-gateway-workflow.md)のPhase Determination表は、各成果物タイプに許可されたティアの上限を明示している。例えば「スクリプト実装(承認済み計画が存在する)」はPhase 4であり、担当エージェントはautomation-engineer(low)である — ここにhighを割り当てるとTier Ceiling違反となる。一方「新規ファイル設計、スキーマ定義」はPhase 1-2であり、architect(high)が担当する。
プラットフォームパリティ — .claude/・.gemini/・.agents/・.codex/・.hermes/を構造的に同一に保つ方法
このリポジトリは5つのプラットフォームを同時にサポートする — Claude Code(.claude/)、Gemini CLI(.gemini/)、Antigravity(.agents/)、Codex(.codex/)、Hermes(.hermes/)。プラットフォームディレクトリが時間の経過とともにずれると(例えば.claude/agents/reviewer.mdは存在するのに.gemini/agents/reviewer.mdが欠けていると)、片方のツールを使うユーザーだけが特定の機能を使えなくなる問題が生じる。スキル層はskills/が単一の情報源(SSOT)であり、sync-skills.tsがこれを5つのプラットフォームディレクトリすべてへ配布する。構造的なずれを防ぐ仕組みがvalidate-templates.tsのプラットフォームパリティ検査である。
ただし検査のスコープには微妙な違いがある。validate-templates.tsはコマンドなどのテンプレート構造を.claude/と.gemini/の2ディレクトリに対してのみ照合し(Antigravity用の.agents/とCodex用の.codex/ツリーは独自の同期経路で管理される)、スキルの内容そのものはSSOTであるskills/をvalidate-skills.tsが検証する。つまり「5プラットフォームが同じ機能を提供するか」は、配布スクリプトとSSOT検証の組み合わせで保証される。第13章で扱う昇格(promote)パイプラインもパリティ検査を昇格前の必須ゲートとして含むため、一部のプラットフォーム用だけ作って他を見忘れた状態では、そもそも正式なvariant(バリアント)になれない。5つのプラットフォームが異なる実行方式を使っていても、提供する機能一覧そのものは常に同じでなければならないという原則を構造検査によって強制しているのである。
最新情報(2026-10) — コマンドパリティのGemini側は、手書きではなく生成されるようになりました。Gemini CLIが読み込むのはTOMLコマンドのみのため、.gemini/commands/<name>.toml ファイルは .claude/commands/<name>.md のSSOTから bun scripts/render-commands.ts で生成され、bun scripts/render-commands.ts --check がドリフトを検出するとCIが失敗します(旧 .md コピーはテンプレートから削除されました)。
graft — マルチプラットフォームフリートのためのリポジトリ文脈グラフ
graft(@nanonets/graft)は、リポジトリ向けにあらかじめ構築しておく文脈グラフである。コードベースを、正確なfile:line範囲を持つ小さく相互リンクされたgraft/マークダウンカードへと索引化し、誰が何を呼び出すかのコールグラフも併せて生成する。狙いは速度である。大きなモノレポを探索するエージェントはgraft ask "<question>"やgraft callers <symbol>を尋ねるだけで、毎ターン同じ文脈を再構築するためにgrepを繰り返しファイル全体を開く代わりに、ソース範囲が埋め込まれた順位付け済みの事前計算された回答を得られる。graftは2026-09-06からワークスペースのルートで稼働していたが、ADR-0076以前は手作業で接続されており、Claude Code専用だった。
2026-09-12のフリート調査(設計文書:2026-09-12-graft-multiplatform-rollout-design.md)により、実際のカバレッジは見た目よりはるかに狭いことが判明した。templates/commonはgraftのスキルファイルとGemini MCPエントリしか配布しておらず、新しくスキャフォールドされたプロジェクトはGemini CLI/Antigravity向けのgraftしか得られず、同じプロジェクトのClaude Code側にはgraftのソースが一切なかった。11プロジェクトのフリート全体で事実上graftはゼロだった。これは.claude/skills/**が通常sync-skills.tsのプラットフォームミラールールに管理される領域である一方、graftのスキルは意図的にSSOTであるskills/ディレクトリの外に置かれているため、どのアップグレードパスもこれを届けたことがなかったからである。さらに、同じMCPサーバーがどの設定ファイルを見るかによってnpx・bunx・ネイティブバイナリという3つの異なる方法で起動されており、Codex/Antigravity/Claude Desktopに対するホストカバレッジは文書化されず暗黙のままだった。
ADR-0076はホストごとの配布マトリクスでこのギャップを埋める。プロジェクト単位の設定をサポートするホストにはリポジトリレベルのMCP登録を行い(Claude Codeの.mcp.json、Gemini/Antigravityの.gemini/settings.json、Codexの.codex/config.toml、OpenCodeのopencode.json)、AGENTS.md/CLAUDE.md/GEMINI.mdに指示ブロックを追加し、プロジェクトスコープを持たないホストにはマシングローバル登録を用いる(Antigravityはgraft init --agents antigravityによるグローバルレジストリ、Claude Desktopはこのホストが作業ディレクトリを渡せず絶対パスのリポジトリパスが必要なため、手書きのclaude_desktop_config.jsonエントリ)。bunx @nanonets/graft mcpがすべてのプラットフォームで共通にコミットされる標準ランチャーとなり、マシングローバル設定ではネイティブバイナリも引き続き使用できる。
既存フリートへの配布は、一回限りの移行パスではなく、第10章§2で扱った同じポリシー駆動アップグレードエンジンに乗って行われる。.mcp.json/opencode.jsonはJSON_MERGE_FILES分類に加わり(そのためプロジェクト固有のMCPサーバーはマージ後も残る)、.claude/skills/graft/**は通常のプラットフォームミラールールより先に同期されるよう特別扱いされ(そのルールはそもそもSSOTの外にあるスキルには届かないため)、.codex/**はADD_IF_MISSINGとしてシードされ、既に自前のconfig.tomlを持つプロジェクトは既存の内容を維持する。ロールアウト時点では、graftスキル自体はSSOTへ移さずClaude専用のまま残し、ルートとtemplates/commonの2箇所でバイト単位で同一のコピーを手動で維持していた。移すとsync-skills.tsがそれをGemini/Antigravity自身のスキルディレクトリへミラーしてしまい、当時このツールについてワークスペースが固定していたシングルプラットフォーム設計を壊してしまうためである。更新(2026-10-01、ADR-0076修正1):この例外は廃止された — 現在skills/graft/SKILL.mdは通常のSSOTスキルとしてsync-skills.tsが5つのプラットフォームディレクトリすべてへミラーし、graft専用の特別扱い(テンプレートツリー同期ルール、パリティスイープ除外、バイト同一性検査)は削除された。鮮度(freshness)は意図的に手動のままにされている(graftのツールは回答前に自ら再更新し、CIやプッシュ前の鮮度ゲートは存在しない)。
新着情報(2026-10) — ワークスペースはgraftのサーフェスをテンプレートとして配布するのをやめました。skills/graft は mirror: false・l2_propagate: false となり、新しいスキャフォールドにはgraftスキルのコピーが入らず、AGENTS.md のgraftブロックはツール所有物です(graft init が生成)。リポジトリコンテキストグラフはスキャフォールディング時に自動でビルドされ続けるため(graft build を優先し、なければ bunx)、graft ask は初日から動作します。
ユニバーサルデザインゲート — L0~L3全体でスペックゲートを均一にする
第10章§4では、下記の実行計画テンプレートにおいてL0/L1実行計画のデザインゲート(0番行)と、それを同期時のFATALブロッカーとして強制するスペックチェック(ADR-0055 Stage 2)をすでに紹介している。この節で扱う2つのADRは、同じガバナンス概念を異なる方向へ拡張するものであり、両者を区別しておく価値がある。
ADR-0068(「ユニバーサルデザイン」)は同期時ゲートではなく、デザインレビューの方法論に関するものである。2026-09-06のレビューにより、ワークスペースはWCAG 2.1 AA準拠(ADR-0065)を技術的な最低基準として強制しているものの、どの層でも加齢・認知負荷・状況的障害・運動能力の差異といった、より広いユーザーの多様性に対してデザインを評価していないことが判明した。ADR-0068はユニバーサルデザインの古典的な7原則(公平な利用、柔軟な利用、単純で直感的な利用、認知可能な情報、エラーへの寛容性、少ない身体的負担、適切な大きさと空間)を、WCAGの上位に位置するレビュー語彙として採用し、Design Foundationの原則集合に認知負荷とエラー復旧という2つの新しい派生基準を追加し、ジャーニーマッピングの過程で多様性プロファイルレビューのステップ(加齢・認知・状況・運動制約の各プロファイルでジャーニーを一度ずつ歩く)を要求する。あるデザインがWCAGには合格しながらユニバーサルデザインには不合格となり得ること、そしてUDはトークン値・色・レイアウトの詳細ではなくレビュー方法論を規律するものであることが明示されている。
ADR-0074(「ユニバーサルデザインゲート」)は、名前は似ているが上記のデザインレビューの視点ではなく、同期時のスペックチェックゲートの適用範囲に関する別の、より後の決定である——つまり単純に「UDにゲートを付けた」ものではない。調査の結果、docs/specs/registry.jsonスペックゲートは新規スキャフォールドされたプロジェクトに構造的に存在せず(ADR-0073がdocs/specsをTEMPLATE_ONLYに分類したため、スキャフォールド時に削除され、アップグレードでも届けられなかった)、既存11フリートプロジェクトのうち5つには完全に欠落していた。AGENTS.mdもL2/L3バリアントプロジェクトをデザインゲートから明示的に除外していた。ADR-0074はこのゲートをすべてのティア(L0~L3)で普遍的にする。同じ基盤となるスペックチェック機構が今やあらゆる場所に適用されるが、その儀式は異なる——L0/L1は既存の完全な0番行実行計画の提示方法を維持し、L2/L3プロジェクトはデザイン文書1つとspec-register.tsによるより軽量な慣習を用いる。docs/specsはTEMPLATE_ONLY_DIRSから除外され、add-if-missingシードとして再分類されることで、スキャフォールドとアップグレードの双方が実際にレジストリを届けられるようになり、既存のE1~E5除外カテゴリはすべてのティアで安全弁として変わらず機能し続ける。
実行計画テンプレート — マルチエージェント作業の構造化された実行設計
PMが複雑な作業を複数のエージェントに分配する際、実行計画(Execution Plan)形式を使用する。この計画は「誰が何をどのティアで、どの順序で」行うかをテーブルで明示し、実行の一貫性を保証する。
標準実行計画フォーマット
| # | Task | Agent | Tier | Model | Spec |
|---|---|---|---|---|---|
| 0 | Create/update design doc → docs/designs/<spec-id>-design.md | architect | High | [model] | NEW |
| 1 | [task description] | [specialist] | High/Medium/Low | [model] | <spec-id> |
| N | /sync "type(scope): message" | pm | Medium | [model] |
Design Gate(Row 0)
Row 0はL0(ワークスペースルート)とL1(共通テンプレート)にのみ強制される。architectがまず設計文書を作成し、PMがこれを検証した後にのみ実装段階(Row 1以降)に進むことができる。L2 variantプロジェクトは自身のワークフローを管理するため、このゲートは適用されない。
Design Gate 例外カテゴリ
Row 0が負担となる単純な作業には、次の5つの例外カテゴリ(E1〜E5)のみが認められる。例外はPMが任意に作ることはできず、以下に定義されたカテゴリのみを使用しなければならない。
| ID | カテゴリ | 説明 |
|---|---|---|
| E1 | memory-log | memory/YYYY-MM-DD.mdセッションログの作成 |
| E2 | changelog | CHANGELOG.md更新のみ |
| E3 | hotfix-typo | 誤字修正、1行変更、些細な修正 |
| E4 | pure-readme | README.md本文テキストのみ(構造/設計変更なし) |
| E5 | sync-only | /sync実行のみ(ライフサイクル終了) |
例外を適用する場合、Row 0のAgent/Tier/Model列は空欄(—)で表示する。
この例外体系は文書ルールに留まらず、同期パイプラインが機械的に強制する。ADR-0055 Stage 2以降、dev-sync.tsのステップ3.9(specレジストリチェック)は、コード変更に対応するspec活動がない場合、同期をFATALでブロックする。これを回避する唯一の方法は、audit.ts --spec-exempt=E1..E5(またはSYNC_SPEC_EXEMPT環境変数)で上記カテゴリの一つを明示することであり、specはdocs/specs/registry.jsonに登録される(2026-08-24時点)。
実践例:PMが作成した実行計画
以下は「agents/pm.mdとスクリプトを更新するプラットフォームパリティ作業」の実際の実行計画例である。
| # | Task | Agent | Tier | Model | Spec |
|---|---|---|---|---|---|
| 1 | Update agents/pm.md | docs-writer | Medium | sonnet | <spec-id> |
| 2 | Update scripts/audit.ts | automation-engineer | Low | haiku | <spec-id> |
| 3 | Update CLAUDE.md §5 | docs-writer | Medium | sonnet | <spec-id> |
| 4 | Update GEMINI.md §5 | docs-writer | Medium | sonnet | <spec-id> |
| 5 | /sync "docs(agents): update pm.md and platform dispatch rules" | pm | Medium | sonnet |
実行順序:Sequential(逐次実行) — プラットフォームパリティのためにCLAUDE.mdとGEMINI.mdを一緒に更新する必要があるため、逐次実行となる。automation-engineerにlowが割り当てられているのはTier Adjustment Ruleに基づくものである。