第10章

L3プロジェクトのアップグレード

L3プロジェクトを作成した後に上位標準(L0/L1)が変更されると何が起きるのか — 答えは「何も起きない」である。第8章 §1で扱ったフォークモデルのため、すでに生まれたL3プロジェクトに新しい変更を実際に反映するには、人が明示的にupgrade-project.tsを実行する必要がある。本章ではその手順を扱う。

出典: ai-workspace-standards/scripts/upgrade-project.ts(v1.10.1時点) ・関連: 第8章 §1 デプロイとSSOT

本章で扱う内容
  • フォークモデルにおいて「アップグレード」がなぜ自動ではなくコマンド実行を要する作業なのか
  • upgrade-project.tsの基本的な使い方と--dry-runを先に行う原則
  • LOCKED・MERGE・DOCS_MERGE・VARIANT_DOCS_SYNC・COMMANDS_SYNC・SYNC_IF_NEWER・PRESERVE・PRUNEの8つのファイル処理方式
  • 自動のgit stashスナップショットと--rollbackによる復元という安全装置
  • 第11章で扱う「昇格」とは方向が正反対である点

なぜ必要か — フォークモデルの裏側

第8章 §1で確認したように、L1はnew-project.tsでプロジェクトをスキャフォールディングする時点で一度だけ内容を渡す。それ以降L3は完全に独立して進化し、L1がどれだけ変わろうと、すでに作成されたL3には何も自動的に反映されない。

問題は、時間が経つにつれてL1側のフックスクリプトが修正され、新しいスキルが追加され、セキュリティ設定が強化されていくことである。こうした変更を個々のL3プロジェクトに反映したいとき、ファイルを一つひとつ手作業で照合するのは現実的ではない。upgrade-project.tsはこの反映作業を自動化しつつ、フォークモデルの核心原則 — 「L3が意図的に変更した部分をむやみに上書きしない」— はそのまま守る。

upgrade-project.ts の使い方

まず--dry-runで何が変わるかを事前に確認する。実際にファイルを操作せず、コンソールに計画のみを出力する。

bun scripts/upgrade-project.ts <project-path> --dry-run

出力内容に問題がなければ、--dry-runを外して再度実行する。

bun scripts/upgrade-project.ts <project-path>
# 任意フラグ: --variant <variant>  --platform claude|antigravity|both
#            --prune-removed  --rollback

--variantはプロジェクトの.claude/template-version.txtに記録された値を自動で読み込むため、多くの場合省略できる。このファイルが存在しない古いプロジェクトでは、実行時に確認プロンプトが表示され、--variantを直接指定する必要がある。

ファイル処理の8分類

スクリプトは性質に応じてファイルを異なる方法で扱う — すべてを一律に「新しい内容で上書き」するわけではない。

分類動作対象例
LOCKED常にテンプレートの内容で上書きする.githooks/*(pre-commitルーティングなど)、.gitattributes
LOCKED (merge-aware)LOCKEDと同様に常にテンプレートを採用するが、マージ認識型 — プロジェクトのみが持つ正規表現・許可リスト(regexes/paths)の項目は保持し、管理対象ルールだけを復元する(v1.10.0以降。以前の無条件上書きはプロジェクト固有の許可リストを失わせていた).gitleaks.toml(mergeGitleaksToml())
MERGEWORKSPACE-MANAGED/COMMON-CLAUDE/COMMON-GEMINI/COMMON-AGENTS/VARIANT-INJECT/DYNAMIC_SKILLSマーカーで囲まれた区間のみをマージし、それ以外のローカル内容はそのまま保持するCLAUDE.md/GEMINI.md(--platformによる)、.gitignoreagents/pm.md
DOCS_MERGEドキュメントにもMERGEと同じマーカー区間マージを適用 — マーカーのない文書だけ例外的に丸ごと上書きする(v1.7.0で追加)AGENTS.mddocs/<variant>.context.mddocs/phase-definitions.md
VARIANT_DOCS_SYNCファイル内の*<ファイル名> version: X.Y脚注バージョン(なければハッシュ)がテンプレートより古い場合のみ更新する(v1.7.0で追加)docs/context.md(v1.9.0から)、docs/engagement-orchestration.mddocs/team-configuration-guide.md
COMMANDS_SYNCハッシュが異なる場合、プラットフォームのコマンドファイルをテンプレートの内容で同期する(v1.7.0で追加).claude/commands/*.md.gemini/commands/*.md
SYNC_IF_NEWERテンプレートのバージョンがプロジェクトのバージョンより新しい場合のみコピーするscripts/*.ts(@versionコメント、JSDocヘッダーを含む)、agents/*.md(frontmatterのversion:)、skills/*/SKILL.md
PRESERVE一覧に表示するのみで、一切手を加えないREADME.mdREADME_ko.mdsrc/
PRUNE(任意)--prune-removedを指定した場合、テンプレートから削除されたscripts/agents/skillsファイルをプロジェクトからも削除する上記SYNC_IF_NEWER対象と同じディレクトリ

v1.10.xから、アップグレードは国プロフィール(国スコープ資産)にも対応する。実行前にプロジェクトの.claude/template-version.txtからcountry=行を読み(なければdocs/countries/ACTIVE.mdの管轄表記で代用)て対象国を判定し、仕上げの書き換え時にはこの行をそのまま保持する — 旧バージョンは書き換え時にこの行を消してしまい、プロジェクトの所属国情報を失わせていた。さらに、すべてのスキル同期が終わった後、レジストリ駆動のpruneがもう一度実行され、国スコープスキル(k-dart/k-law/k-kosis)が該当国以外のプロジェクトに再注入されていれば削除する — スキャフォールディング時の整理結果をアップグレードのたびに取り消してしまう事態を防ぐためである。ただし、ローカルで意図的に改変されたフォークは⚠️ CONFLICT警告付きでそのまま保持される。

SYNC_IF_NEWER対象のファイルをローカルで直接修正済みの状態で、かつテンプレート側のバージョンがより新しい場合、スクリプトは⚠️ CONFLICTと表示しつつも、最終的にはテンプレートの内容で上書きする。「上書き前に確認する」動作ではなく、「警告のみして進める」動作である点を覚えておく必要がある — だからこそ、以下の安全装置が重要になる。

安全装置 — スナップショットとロールバック

実行前(--dry-runでない場合)、スクリプトは自動的にgit stash push -m pre-upgrade-snapshot-YYYYMMDDを実行し、現在の作業ツリーの状態をスナップショットとして残す。アップグレードの結果が気に入らない場合は、次のコマンドで即座に元に戻せる。

bun scripts/upgrade-project.ts <project-path> --rollback

このコマンドは、直前に作成されたpre-upgrade-snapshot-*スタッシュを探し出し、git stash popで復元する。アップグレード自体はコミットを作成しないため、結果を確認した後は通常どおりgit diffで変更内容を確認し、自分でコミットする必要がある。

仕上げの段階として、.claude/template-version.txtが新しいバージョンに更新され(このときcountry=行は保持される)、.gitleaks.toml・pre-commitフック・.gitattributes(eol=lf)・.gitignore(.envパターン)・git core.hooksPathといったセキュリティブートストラップ項目が自動でチェックされる(第3章のガードレール原則と同じ項目である)。core.hooksPathが誤っている場合、スクリプトが自動で修正する。

昇格との方向の違い

第11章で扱う「昇格」と本章の「アップグレード」は名前こそ似ているが、方向は正反対である。

  • 昇格(l3-to-variant-pipeline.ts、第11章) — L3 → L2。自分が作成したプロジェクトの変更を公式variantテンプレートへ引き上げ、他の人も使えるバリアント(variant)にする作業。
  • アップグレード(upgrade-project.ts、本章) — L1 → L3。公式テンプレートの最新の変更を、すでに作成した自分のプロジェクトに取り込む作業。

両スクリプトは互いに逆方向へファイルを流すだけで、どちらか一方が他方を代替するものではない。テンプレートに貢献したいなら昇格を、すでに作成したプロジェクトを最新の状態に保ちたいならアップグレードを使う。

本章で扱ったスクリプトの動作(フラグ、ファイル分類、安全装置)は、ai-workspace-standardsリポジトリのscripts/upgrade-project.ts(v1.10.1)のソースを直接確認して執筆した。このハンドブックのリポジトリには該当スクリプトが含まれていないため、実際の実行結果は必ず最新のソースと照らし合わせて確認すること。