feat: AI-DLC の更新伝播メカニズムを導入 (Phase 1-3) #2

Merged
hardlitchi merged 3 commits from feat/ai-dlc-update-mechanism into main 2026-08-10 07:26:33 +00:00
Owner

取り込み先プロジェクトへ上流 AI-DLC の更新を届けつつ、下流のテーラリングを壊さない仕組みを3フェーズで実装しました。

背景

従来の配備ロジックは二択しかなく、その中間がありませんでした。

箇所 挙動 更新時の結果
copyFileSyncIfNotExists 既存があれば全スキップ 上流の改善が一切届かない
copyDirRecursiveSync 無条件上書き テーラリングした Skill が消える

さらに配備先にバージョン情報が残らないため、何が入っているかも、どこが手で書き換えられたかも判定できませんでした。

中核原則: 1つのファイルを上流と下流で共同所有しない

所有者を必ずどちらか一方に決め、境界をディレクトリまたはマーカーで物理的に区切ります。

consumer-project/
├── .ai-dlc/                  # 🔒 上流所有(まるごと置換可能・要コミット)
│   ├── manifest.json         #    配備台帳。更新差分の判定基準
│   └── skills/
├── .ai-dlc-local/            # ✏️ プロジェクト所有(上流は初回配置後に触らない)
│   ├── ai-dlc-config.json
│   └── skills/
├── AGENTS.md                 # 🔀 管理ブロック(マーカー間だけが上流所有)
└── docs/ai-dlc/              # 📝 雛形。初回だけ配置され以降は放置

コミット構成

各コミットは単体でチェックアウトしても動作します(初回導入・再実行の冪等性を3コミットすべてで確認済み)。

1. 3d21849 配備台帳と3方向差分による更新伝播 (Phase 1)

配備内容を .ai-dlc/manifest.json に sha256 で記録し、「上流が変えたか」「ローカルが変えたか」を独立に判定します。

ローカル編集 上流変更 結果
なし あり 🔄 自動更新
あり なし ✏️ ローカル編集を保持
あり あり ⚠️ 要判断 — 既存は保護し、上流版を .ai-dlc-new に出力
  • Skill をファイル単位の owned 同期へ変更し、無条件上書きを廃止
  • pre-commit フックは AI-DLC Guard マーカーで判定し、他ツールのフックを奪わない
  • テーラリング値を台帳へ永続化し、更新時の既定値巻き戻りを防止
  • .sh / .ps1 フォールバックは台帳を扱えないため初回導入専用化
  • ハッシュは CRLF を LF へ正規化(Windows での偽のローカル編集判定を防止)

2. 710eec0 所有権を分離し AGENTS.md を管理ブロック方式へ (Phase 2)

ステアリングファイルは各AIツールがルート直下の固定名を読むため分割できません。そこでマーカーで境界を引き、上流はマーカー間の本文だけを差し替えます。

<!-- AI-DLC:BEGIN v2.0.0 — 自動生成領域。… -->
(上流のルール。更新時はここだけが差し替わる)
<!-- AI-DLC:END -->

## 🧩 プロジェクト固有ルール
(この行より下は更新で書き換わらない)

ブロック外の記述は更新の判定対象にすら入らないため、上流がルールを追加してもコンフリクトなしで自動反映されます。

移行も自動化しています。

移行前の状態 挙動
マーカーなし・上流と同一内容 🧩 自動でマーカーを付与
マーカーなし・手編集済み ⚠️ 原本は無傷、既存内容をブロック下に温存した移行案を提示
v1 の skills/(未編集) 🚚 .ai-dlc/skills/ へ自動移動
v1 の skills/(編集済み) ⚠️ 移動せず据え置き+通知

3. 19c547f sync / diff / doctor コマンドと配布経路を整備 (Phase 3)

コマンド 用途
ai-dlc sync 配備・更新
ai-dlc diff 行単位の差分表示(一切書き込まない・依存なしの LCS 実装)
ai-dlc doctor バージョン差・台帳整合性・未解決コンフリクト・乖離内訳+既存の衛生診断

終了コード: 0 正常 / 1 エラー・--strict 違反 / 2 要判断あり

  • templates/ci_cd/ai_dlc_update_check.yml: 週次で上流更新を検知し、更新 PR を自動発行。下流は PR をレビューして merge するだけになります
  • docs/PUBLISHING.md: 配布・公開手順とバージョニング方針。npm 公開は必須ではなく、npx は Git URL から直接解決できます
  • setup_ai_dlc.js は ai-dlc sync の後方互換ラッパへ縮小(従来の呼び出し方は維持)

検証

使い捨てプロジェクトに対して以下17項目を確認済みです。

  • 初回導入 / 冪等性 / diff の「差分なし」判定
  • テーラリング(ブロック外追記)と上流更新の共存 — コンフリクトなしで両立
  • ブロック内編集の保持
  • コンフリクト時の原本保護・提案ファイル出力・doctor での検知・exit 2
  • --force での解決とバックアップ生成
  • v1 レイアウトからの移行(未編集は移動、編集済みは据え置き+通知)
  • マーカーなし手書きファイルの保護と移行案提示
  • 他ツールの pre-commit フックの保護
  • --dry-run で副作用ファイルが一切生成されないこと

レビュー時の注目点

  • templates/setup/lib/blocks.js の normalizeBody() — 「書き出す形」と「ハッシュを取る形」を揃えるための関数です。ここがずれると未編集のブロックが毎回ローカル編集と誤検出されます(実装中に実際に踏みました)
  • templates/setup/lib/migrate.js — 移行時にファイルを削除する条件(ハッシュ一致時のみ)
  • 破壊的変更のため package.json を 2.0.0 へ上げています
取り込み先プロジェクトへ上流 AI-DLC の更新を届けつつ、下流のテーラリングを壊さない仕組みを3フェーズで実装しました。 ## 背景 従来の配備ロジックは二択しかなく、その中間がありませんでした。 | 箇所 | 挙動 | 更新時の結果 | |---|---|---| | `copyFileSyncIfNotExists` | 既存があれば全スキップ | 上流の改善が**一切届かない** | | `copyDirRecursiveSync` | 無条件上書き | テーラリングした Skill が**消える** | さらに配備先にバージョン情報が残らないため、何が入っているかも、どこが手で書き換えられたかも判定できませんでした。 ## 中核原則: 1つのファイルを上流と下流で共同所有しない 所有者を必ずどちらか一方に決め、境界をディレクトリまたはマーカーで物理的に区切ります。 ``` consumer-project/ ├── .ai-dlc/ # 🔒 上流所有(まるごと置換可能・要コミット) │ ├── manifest.json # 配備台帳。更新差分の判定基準 │ └── skills/ ├── .ai-dlc-local/ # ✏️ プロジェクト所有(上流は初回配置後に触らない) │ ├── ai-dlc-config.json │ └── skills/ ├── AGENTS.md # 🔀 管理ブロック(マーカー間だけが上流所有) └── docs/ai-dlc/ # 📝 雛形。初回だけ配置され以降は放置 ``` ## コミット構成 各コミットは**単体でチェックアウトしても動作**します(初回導入・再実行の冪等性を3コミットすべてで確認済み)。 ### 1. `3d21849` 配備台帳と3方向差分による更新伝播 (Phase 1) 配備内容を `.ai-dlc/manifest.json` に sha256 で記録し、「上流が変えたか」「ローカルが変えたか」を独立に判定します。 | ローカル編集 | 上流変更 | 結果 | |---|---|---| | なし | あり | 🔄 自動更新 | | あり | なし | ✏️ ローカル編集を保持 | | あり | あり | ⚠️ 要判断 — 既存は保護し、上流版を `.ai-dlc-new` に出力 | - Skill をファイル単位の `owned` 同期へ変更し、無条件上書きを廃止 - pre-commit フックは `AI-DLC Guard` マーカーで判定し、他ツールのフックを奪わない - テーラリング値を台帳へ永続化し、更新時の既定値巻き戻りを防止 - `.sh` / `.ps1` フォールバックは台帳を扱えないため初回導入専用化 - ハッシュは CRLF を LF へ正規化(Windows での偽のローカル編集判定を防止) ### 2. `710eec0` 所有権を分離し AGENTS.md を管理ブロック方式へ (Phase 2) ステアリングファイルは各AIツールがルート直下の固定名を読むため分割できません。そこでマーカーで境界を引き、上流はマーカー間の本文だけを差し替えます。 ```markdown <!-- AI-DLC:BEGIN v2.0.0 — 自動生成領域。… --> (上流のルール。更新時はここだけが差し替わる) <!-- AI-DLC:END --> ## 🧩 プロジェクト固有ルール (この行より下は更新で書き換わらない) ``` ブロック外の記述は更新の判定対象にすら入らないため、上流がルールを追加しても**コンフリクトなしで自動反映**されます。 移行も自動化しています。 | 移行前の状態 | 挙動 | |---|---| | マーカーなし・上流と同一内容 | 🧩 自動でマーカーを付与 | | マーカーなし・手編集済み | ⚠️ 原本は無傷、既存内容をブロック下に温存した移行案を提示 | | v1 の `skills/`(未編集) | 🚚 `.ai-dlc/skills/` へ自動移動 | | v1 の `skills/`(編集済み) | ⚠️ 移動せず据え置き+通知 | ### 3. `19c547f` sync / diff / doctor コマンドと配布経路を整備 (Phase 3) | コマンド | 用途 | |---|---| | `ai-dlc sync` | 配備・更新 | | `ai-dlc diff` | 行単位の差分表示(**一切書き込まない**・依存なしの LCS 実装) | | `ai-dlc doctor` | バージョン差・台帳整合性・未解決コンフリクト・乖離内訳+既存の衛生診断 | 終了コード: `0` 正常 / `1` エラー・`--strict` 違反 / `2` 要判断あり - `templates/ci_cd/ai_dlc_update_check.yml`: 週次で上流更新を検知し、更新 PR を自動発行。**下流は PR をレビューして merge するだけ**になります - `docs/PUBLISHING.md`: 配布・公開手順とバージョニング方針。npm 公開は必須ではなく、`npx` は Git URL から直接解決できます - `setup_ai_dlc.js` は `ai-dlc sync` の後方互換ラッパへ縮小(従来の呼び出し方は維持) ## 検証 使い捨てプロジェクトに対して以下17項目を確認済みです。 - 初回導入 / 冪等性 / `diff` の「差分なし」判定 - テーラリング(ブロック外追記)と上流更新の共存 — コンフリクトなしで両立 - ブロック内編集の保持 - コンフリクト時の原本保護・提案ファイル出力・`doctor` での検知・exit 2 - `--force` での解決とバックアップ生成 - v1 レイアウトからの移行(未編集は移動、編集済みは据え置き+通知) - マーカーなし手書きファイルの保護と移行案提示 - 他ツールの pre-commit フックの保護 - `--dry-run` で副作用ファイルが一切生成されないこと ## レビュー時の注目点 - `templates/setup/lib/blocks.js` の `normalizeBody()` — 「書き出す形」と「ハッシュを取る形」を揃えるための関数です。ここがずれると未編集のブロックが毎回ローカル編集と誤検出されます(実装中に実際に踏みました) - `templates/setup/lib/migrate.js` — 移行時にファイルを削除する条件(ハッシュ一致時のみ) - 破壊的変更のため `package.json` を `2.0.0` へ上げています
取り込み先プロジェクトへ上流の更新を届けつつ、下流のテーラリングを
壊さないための基盤を整備する。

従来の配備ロジックは「既存があれば全スキップ」(copyFileSyncIfNotExists)
と「無条件上書き」(copyDirRecursiveSync) の二択しかなく、更新が一切
届かないか、テーラリングした Skill が失われるかのどちらかだった。

配備内容を .ai-dlc/manifest.json に sha256 で記録し、次回実行時に
「上流が変えたか」「ローカルが変えたか」を独立に判定する。両方が
変わった場合だけをコンフリクトとして人間に委ね、既存ファイルは
決して破壊しない (上流版は .ai-dlc-new へ並置)。

- lib/manifest.js: 台帳の読み書きとハッシュ計算
  CRLF を LF へ正規化し、Windows での偽のローカル編集判定を防ぐ
- lib/sync.js: 配備モード (owned / seed-once) と3方向差分の判定
- lib/report.js: 同期結果のサマリとコンフリクト解決の案内
- lib/deploy.js: Skill をファイル単位の owned 同期へ変更し、
  無条件上書きを廃止。pre-commit フックは AI-DLC Guard マーカーで
  判定し、他ツールのフックを奪わない
- CLI に --dry-run / --force / --verbose を追加
- テーラリング値を台帳へ永続化し、更新時の既定値巻き戻りを防ぐ
- .sh / .ps1 フォールバックは台帳を扱えないため初回導入専用とし、
  管理下プロジェクトの更新は明示的に拒否する

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Phase 1 の台帳の上に「1つのファイルを上流と下流で共同所有しない」と
いう中核原則を実装する。所有権をファイルまたはマーカーで物理的に
分離することで、テーラリングと更新の反映が恒久的に両立する。

ステアリングファイルは各AIツールがルート直下の固定名を読むため分割
できない。そこで AI-DLC:BEGIN / AI-DLC:END マーカーで境界を引き、
上流はマーカー間の本文だけを差し替える。ブロック外に書いた
プロジェクト固有ルールは更新の判定対象にすら入らないため、上流が
ルールを追加してもコンフリクトなしで自動反映される。

- lib/blocks.js: マーカーの組立・抽出・置換
  normalizeBody() で「書き出す形」と「ハッシュを取る形」を必ず揃える。
  ここがずれると未編集のブロックが毎回ローカル編集と誤検出される
- lib/sync_block.js: managed-block の同期。比較対象はファイル全体
  ではなくマーカー間の本文
- lib/sync_core.js: 配備モードと判定結果の共通プリミティブを分離
- lib/migrate.js: v1 の skills/ を .ai-dlc/skills/ へ移行。
  ハッシュが一致する(未編集の)ファイルだけを移動し、編集済みは
  据え置いて通知する。勝手に消さないことで取りこぼしを防ぐ
- templates/ownership/: .ai-dlc/(上流所有) と .ai-dlc-local/(下流所有)
  の役割を説明する README を配備
- .ai-dlc-local/ai-dlc-config.json はサンプル値ではなく実際に採用された
  プロファイル値を書き出す。ダミー値を置くと次回実行でそれが読み込まれ、
  プロジェクト名が化ける
- マーカーの無い既存ファイルは、上流と同一なら自動でラップし、
  手編集済みなら既存内容をブロック下に温存した移行案を提示する

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
下流が更新に迷わないための道具立てを揃える。更新の運用コストを
下げる決め手は「何が変わるかを事前に確認できること」と
「更新 PR が自動で立つこと」の2点にある。

- bin/ai-dlc.js: サブコマンド方式の CLI エントリポイント
  終了コード 0=正常 / 1=エラー・strict違反 / 2=要判断のコンフリクト
- lib/cmd_diff.js: 一切書き込まずに行単位の差分を提示する。
  更新前の確認をワンステップにする
- lib/text_diff.js: 依存パッケージなしの LCS 行差分。対象は小さな
  Markdown / 設定ファイルのため素直な動的計画法で足りる
- lib/cmd_doctor.js: バージョン差・台帳整合性・未解決の .ai-dlc-new・
  上流との乖離の内訳をまとめて診断し、既存の rule_pruner /
  slop_detector も取り込む。これらは process.exit を呼ぶため
  子プロセスで実行する
- lib/cmd_sync.js: 配備処理を再利用可能な形へ切り出し、
  setup_ai_dlc.js は後方互換のラッパへ縮小
- templates/ci_cd/ai_dlc_update_check.yml: 週次で上流の新バージョンを
  検知し sync を実行して更新 PR を発行する。下流は PR をレビューして
  merge するだけになる
- docs/PUBLISHING.md: 配布・公開手順とバージョニング方針。
  npm 公開は必須ではなく、npx は Git URL から直接解決できる
- package.json に bin / files を追加(npm 公開時にそのまま使える)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
hardlitchi deleted branch feat/ai-dlc-update-mechanism 2026-08-10 07:26:33 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
skill-sets/ai-dlc!2
No description provided.