consolidate-concepts について
複数の `.plain` モジュールにある共通概念を、共有インポートモジュールに集約するスキルです。分析、計画、構造変更を案内し、明示的な承認を求めたうえで、機能、実装、テスト要件を維持します。
主な機能
- 01概念と依存関係の一覧化
- 02共有インポートモジュールの計画
- 03インポートとエクスポートの更新
- 04動作と各要件の維持
- 05参照と構造の検証
活用シーン
- 01モジュール間の概念定義の重複解消
- 02長いエクスポート概念リストの簡素化
- 03モジュール分割後のドメイン定義の共有
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ plainlang/ plain-forge --skill consolidate-conceptsインストール後、Claude Code で/consolidate-conceptsを入力して読み込まれたか確認します。
詳細
概念の統合
まずルールを読み込んでください。 .plain ファイルを読む、編集する、または書き込む前に、load-plain-reference スキルを呼び出し、案内されたルールファイルを読んでください。この会話ですでに load-plain-reference が実行されている場合に限り、省略できます。
使用する場面
- 複数のモジュールが、同じ、または密接に関連する概念をそれぞれ独立して定義している場合。
requiresチェーンで、定義の共有に長いexported_conceptsリストが使われており、インポートにしたほうがシンプルな場合。refactor-moduleによる分割後、共有概念が重複したり、不自然な形でエクスポートされたりしている場合。- ユーザーが、複数のモジュールで使われるドメイン概念の信頼できる唯一の情報源を求めている場合。
基本原則
これは構造のリファクタリングです。影響を受けるすべてのモジュールの動作は、同一に保つ必要があります。機能仕様、実装要件、テスト要件は変更しません。概念定義のみを分散した場所から共通のインポートモジュールに移し、各モジュールの import リストを更新して参照先を変更します。
入力
統合元となるモジュールの一覧と、任意で新規または既存のインポートモジュール名を指定します。指定がない場合は、ユーザーに確認してください。
フェーズ 1 — モジュール間の概念を分析する
- すべてのソースモジュールを読みます。 対象となる各
.plainファイルについて、フロントマター、定義、実装要件、テスト要件、機能仕様を含むファイル全体を読みます。また、importとrequiresのチェーンも読みます。 - 概念の一覧を作成します。 すべてのソースモジュールで定義されている各概念について、次の情報を記録します。
- 定義場所(ファイル名と行番号)
- 参照しているモジュール(定義、機能仕様、実装要件、テスト要件のいずれか)
- 現在
exported_conceptsリストに含まれているかどうか - 定義内で参照している他の概念(依存関係グラフ)
- 統合候補を特定します。 次のいずれかに該当する概念は、統合する必要があります。
- あるモジュールで定義され、別のモジュールの仕様から参照されている(現在は
exported_conceptsで共有されている) - 複数のモジュールに重複して定義されている
- 複数のモジュールで共有する用語集に属する、基盤となるドメイン概念である
- あるモジュールで定義され、別のモジュールの仕様から参照されている(現在は
- 各モジュール内に残す概念を特定します。 次のいずれかに該当する概念は、そのモジュール内に残す必要があります。
- そのモジュールの仕様と定義の中だけで使用されている
- 他のモジュールにとって意味を持たない、内部実装の詳細である
フェーズ 2 — 統合を計画する
計画をユーザーに提示し、変更を加える前に明示的な承認を得ます。
2a. 対象のインポートモジュールを選ぶ
- 新しいインポートモジュール —
template/に新しい.plainファイルを作成します。共有するドメインを反映した名前を選びます(例:template/myapp-concepts.plain)。 - 既存のインポートモジュール — 影響を受けるモジュールがすでに使用しているインポートモジュールに概念を追加します。これにより、インポート参照を増やさずに済みます。
対象が既存のインポートモジュールの場合は、その内容を把握するため、ファイル全体を読みます。
2b. 移動する概念を決める
統合候補ごとに、次の点を確認します。
- その概念を、現在のモジュールの
***definitions***セクションから削除する。 - その概念を、対象のインポートモジュールの
***definitions***セクションに追加する。 - 属性と制約に関するすべてのサブ箇条書きを含め、概念の定義全文をそのまま移動する。
2c. 対象モジュール内での概念の順序を決める
インポートモジュール内では、概念が参照先の概念より後に定義されるように並べる必要があります。フェーズ 1 で作成した依存関係グラフを使って、妥当なトポロジカル順序を決定します。
2d. インポートとエクスポートの変更を決定する
影響を受ける各モジュールについて、フロントマターの変更を決定します。
| 変更 | 条件 |
|---|---|
import リストに新しいインポートを追加する | モジュールが対象をまだインポートしていない場合 |
exported_concepts から概念を削除する | 定義を共有する目的でのみエクスポートされていた概念。今後はインポートで提供されます |
exported_concepts に概念を残す | 下流モジュールがエクスポート経由で引き続き必要とする概念(下流モジュールが新しいテンプレートをインポートしないため) |
重要: import は、インポートするモジュールに定義を提供します。requires モジュールの exported_concepts は、ビルドチェーン内の下流モジュールに概念を提供します。下流モジュールが共有テンプレートを直接 import するようになった場合、その概念は exported_concepts から削除できます。下流モジュールがテンプレートをインポートしない場合、その概念はエクスポートしたままにする必要があります。
2e. 計画を提示する
ユーザーに以下の内容をまとめて提示します。
- 対象のインポートモジュール(新規または既存)とそのパス
- 移動する概念の一覧と、それぞれの移動元モジュール
- ローカルに残す概念の一覧とその理由
- モジュールごとのフロントマターの変更(
importの追加、exported_conceptsからの削除) - 機能仕様、実装要件、テスト要件に変更がないことの確認
作業を進める前に、ユーザーから明示的な承認を得てください。
フェーズ 3 — 実行
3a. インポートモジュールを作成または更新する
新しいインポートモジュールを作成する場合:
- YAML フロントマターを含む
template/<name>.plainを作成します。別のインポートから概念を必要とする場合は、そのモジュールを独自のimportリストに追加します。 - 依存関係の順序に従って、統合したすべての概念を含む
***definitions***セクションを追加します。 ***functional specs***は追加しないでください。インポートモジュールに含めることはできません。
既存のインポートモジュールを更新する場合:
- 現在のファイルを読みます。
- 既存の概念との依存関係の順序を考慮して、新しい概念を
***definitions***セクションに挿入します。 - ファイル内の既存の概念、またはそのファイル自身がインポートするモジュール内の概念と名前が重複していないことを確認します。
3b. 各ソースモジュールを更新する
概念を移動した各モジュールについて:
- モジュールの
***definitions***セクションから概念定義を削除します。すべてのサブ項目を含め、定義全体を削除してください。 - モジュールの YAML フロントマターの
importリストにインポートを追加します(まだ追加されていない場合)。 exported_conceptsを更新します — 2d の説明に従って、エクスポートする必要がなくなった概念を削除します。***functional specs***、***implementation reqs***、***test reqs***には手を加えないでください — これらのセクションにある概念への参照(:ConceptName:)は、概念がインポートによって提供されるようになるため、そのままにします。
3c. 下流モジュールを更新する(該当する場合)
概念がモジュールの exported_concepts から削除され、下流モジュールがその概念に依存している場合:
- 下流モジュールの
importリストに新しいインポートを追加し、概念を直接取得できるようにします。 - 下流モジュールの仕様内のすべての概念参照を引き続き解決できることを確認します。
フェーズ 4 — 検証
4a. 概念の利用可能性を確認する
影響を受けるすべてのモジュール(ソースモジュール、下流モジュール、インポートモジュール自体)について:
- 機能仕様で参照されるすべての
:Concept:を解決できる(ローカルで定義されている、インポート経由で利用できる、またはrequiresのエクスポートで提供される) - 定義内で参照されるすべての
:Concept:は、その概念を参照する概念より前に定義されている - 実装要件およびテスト要件で参照されるすべての
:Concept:を解決できる
4b. 重複がないことを確認する
- インポートモジュールとソースモジュールの両方で同じ概念が定義されていない
- インポートモジュールと、ソースモジュールが使用する別のインポートの両方で同じ概念が定義されていない
- 各モジュールの完全な解決範囲(ローカル+インポート+
requiresのエクスポート)内で、概念名が一意である
4c. 定義の整合性チェック
- 移動した各概念の定義文が元の内容と完全に一致していること(言い換えやサブ箇条書きの欠落がないこと)
- インポートモジュール内の概念の順序が依存関係グラフに従っていること(前方参照がないこと)
4d. 動作変更がないことのチェック
- いずれのモジュールでも
***functional specs***が変更されていないこと - いずれのモジュールでも
***implementation reqs***が変更されていないこと - いずれのモジュールでも
***test reqs***が変更されていないこと - テスト用の plain ファイルが変更されていないこと
4e. 構造の検証
インポートモジュールについて:
- ファイルが
template/ディレクトリにあること -
***functional specs***を含まないこと -
requiresを使用していないこと - YAML フロントマターが正しくフォーマットされていること
各ソースモジュールについて:
- YAML フロントマターの
importリストに対象のインポートモジュールが含まれていること -
exported_conceptsが正しいこと(エクスポートしすぎていないこと、必要なエクスポートが欠けていないこと) - モジュールに少なくとも1つの機能仕様と1つの実装要件が残っていること
4f. 変更したすべてのファイルを読む
変更した各 .plain ファイルをすべて読み、変更内容をユーザーに提示して承認を得ます。ユーザーから変更の依頼があった場合は、それを適用して再検証します。
よくある落とし穴
ローカルでのみ使用される概念を移動してしまう
概念が1つのモジュール内でしか参照されていない場合、それを共有インポートに統合すると不要な結合が生じます。ローカルに残してください。
下流モジュールの更新を忘れる
概念を exported_concepts から削除すると、その概念を参照するソースモジュールを requires するモジュールは、共有テンプレートを新たにインポートしない限り動作しなくなります。依存関係の全体を必ず追跡してください。
概念の順序を崩してしまう
インポートモジュール内の概念は、トポロジカル順に並べる必要があります。定義内で :Meal: が :MealType: を参照する場合、:MealType: を先に記述してください。ソースモジュールでは正しい順序になっていたとしても、異なるモジュールの概念を統合するときは、有効な順序に改めて並べ直す必要があります。
循環インポートを作成してしまう
インポートモジュールは、直接または間接的に自分自身をインポートするモジュールを import できません。共有概念が既存のテンプレートの概念を参照する場合は、新しいインポートモジュールからそのテンプレートをインポートする必要があります。逆にしてはいけません。
exported_concepts から概念を早まって削除してしまう
exported_concepts から概念を削除できるのは、その概念を必要とするすべての下流モジュールが、今後は import を介して取得できる場合に限ります。共有テンプレートをインポートしない下流モジュールが1つでもある場合は、そのエクスポートを維持してください。
検証チェックリスト
- 実行前にユーザーが統合計画を確認した
- 移動したすべての概念が、元と同一のテキストでインポートモジュールに定義されている
- インポートモジュール内の概念が有効な依存関係順になっている
- インポートモジュールとソースモジュールの両方で定義されている概念がない
- 影響を受けるすべてのモジュールの
importリストに対象のインポートモジュールが含まれている -
exported_conceptsが正しく更新されている(必要なエクスポートの欠落や不要なエクスポートがない) - 影響を受けるすべてのモジュールで、概念への参照が正しく解決される
- 機能仕様、実装要件、テスト要件、テスト用の plain ファイルが変更されていない
- インポートモジュールが
template/にあり、機能仕様もrequiresも含まない - 循環インポートが発生していない
- 必要に応じて下流モジュールが更新されている
- ユーザーが最終結果を承認した