add-functional-specs について
add-functional-specsは、単一仕様の作成手順を、順序付けた複数仕様に適用するスキルです。各仕様を挿入する前に複雑さと競合を確認し、任意の適合テストを追加します。
主な機能
- 01依存順に仕様を作成
- 02仕様ごとの複雑さ確認
- 03既存仕様との一括競合分析
- 04仕様を順次挿入
- 05各仕様のテスト追加
活用シーン
- 01複数の関連機能を仕様化
- 02確認を省かずに一括作成
- 03順序付き仕様と適合テストの追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ plainlang/ plain-forge --skill add-functional-specsインストール後、Claude Code で/add-functional-specsを入力して読み込まれたか確認します。
詳細
機能仕様を追加する
最初にルールを読み込んでください。 .plain ファイルを読む、編集する、または書き込む前に、load-plain-reference スキルを実行し、案内されたルールファイルを読んでください。この会話ですでに load-plain-reference が実行されている場合のみ、省略できます。
使用するタイミング
- ユーザーが複数の機能仕様をまとめて追加するよう求めた場合(例:「この3つの仕様を追加して」「この機能を箇条書きで仕様化して」)。
- 上位のスキルまたはワークフロー(
forge-plain、add-feature、debug-specs)で、関連する仕様をひとまとまり作成する必要がある場合。 - 個別の仕様ごとに分析を実行せず、複数の機能仕様を書きたくなった場合。
追加する仕様が1つだけの場合は、代わりに add-functional-spec スキルを使用してください。いずれの場合も、複雑さと競合のチェックを確実に実行するため、***functional specs*** セクションを手作業で編集してはいけません。新しい項目は、必ずこれら2つのスキルのいずれかを通して追加してください。
ワークフロー
このスキルでは、add-functional-spec を1つずつ順番に適用し、省略は一切しません。まとめて追加する場合も、仕様ごとの厳密な手順を省くことはできません。
- 対象の
.plainファイルを特定します。 判断できない場合は、ユーザーに確認します。 - 既存の定義、実装要件、すべての機能仕様(
import/requiresをたどって参照されるものも含む)を把握するため、ファイル全体を読みます。 - 追加する仕様をすべて、記載する順序に従って下書きします。各仕様には
semantic-ids.mdに従って個別の func-id を付け、モジュール内および今回の一括追加内で重複しないようにします。下書きは作業用リストに保持し、まだ挿入しません。次に進む前に、すべての下書きに対してconcise-specs.mdに記載されたレビューを実行し、事実をすべて保てる最短の表現になるよう整えます。 - 下書きした仕様を順番に1つずつ処理します。
-
複雑さを分析します。 その仕様に対して
analyze-if-func-spec-too-complexを実行します。判定がTOO COMPLEXの場合は、break-down-func-specを実行し、作業用リストの該当項目を分割後の小さな仕様に置き換えます(順序は維持します)。その後、この手順を最初の分割後仕様からやり直します。 -
競合を確認します。 次の項目をすべて含む単一の入力セットで、
analyze-func-specsを1回だけ実行します。- 新しい仕様
- ファイル内およびその
requiresチェーン内にある既存の機能仕様すべて - すでに挿入済みの、この一括追加内の仕様すべて
一括分析ツールは1回の呼び出しですべての競合ペアを返します。ペアごとの分析ツールを使って、競合ペアごとに繰り返し実行してはいけません。報告された競合ペアごとに
resolve-spec-conflictを実行します。解決内容(新しい仕様、既存の仕様、またはその両方を修正する場合があります)を反映し、判定がCOMPATIBLEになるまで、変更対象の集合に対してanalyze-func-specsをもう一度1回実行します。 -
仕様を
***functional specs***セクションに追加します。見出しを# <func-id>とし、その後に本文を続けます。仕様は時系列順に並べ、新しい項目は末尾に追加します(既存の仕様を新しい仕様の後に置く必要があるまれな場合は、正しい位置に挿入します)。
-
- ファイルをもう一度読み、追加した一括分の配置、順序、構文が正しいことを確認します。
- テスト用の plain ファイルを書きます。モジュールで適合性テストが有効になっている場合は、追加した機能ごとに、順番に
add-test-scenariosを1回実行します。
順序が重要です。新しい仕様は、複雑さと競合のチェックに合格してから初めて挿入されます。そのため、後続の仕様は常に、すでに検証済みのファイルに対してチェックされます。
ルール
add-functional-spec のルールはすべて、個々の仕様に適用されます。このスキルを単独で使えるよう、以下に再掲します。
複雑さの上限(仕様ごと)
各機能仕様が求める変更コード量は、最大200行でなければなりません。仕様が大きすぎる場合は、break-down-func-spec を使用して、独立した小さな仕様に分割します。仕様本文に LOC の見積もりを含めてはいけません。
時系列順序
仕様は上から下へ段階的にレンダリングされます。レンダラーは後続の仕様を把握していません。コンテキストに含まれるのは、すでにレンダリングされた仕様のみです。
- 新しい仕様では、先行する仕様で定義された動作を参照できます。
- 新しい仕様では、後続する仕様について何も前提にできません。
- 各仕様がそれより前の仕様にのみ依存するよう、バッチの順序を決めてください。2つの新しい仕様が相互に参照する場合は、依存する仕様を後に配置します。
言語に依存しない記述
特定の言語やフレームワークに結び付いた実装上の構文ではなく、動作、概念、ドメインロジックの観点から記述してください。言語固有の型、ジェネリクス構文、フレームワークのアノテーションなどは避けてください。null 値、JSON の型、HTTP ステータスコードなど、一般的な技術用語は使用できます。言語固有の指示は ***implementation reqs*** に記載してください。
矛盾の禁止(仕様ごとに1回のバッチ呼び出しで網羅)
新しい仕様は、互いに矛盾してはならず、既存の機能仕様とも矛盾してはなりません。仕様間の矛盾は、最も重大な結果を招きます。矛盾チェックでは、次のすべてを対象にしてください。
- 新規仕様と既存仕様のすべての組み合わせ
- バッチ内の新規仕様同士のすべての組み合わせ
この網羅性は、挿入する仕様ごとに analyze-func-specs を1回実行し、新規仕様、すべての既存仕様、およびこのバッチで既に挿入されたすべての仕様を、1つのセットとして渡すことで実現します。バッチ分析ツールは、1回の呼び出しで矛盾するすべての組み合わせを一覧表示します。組み合わせごとの分析ツールは呼び出さないでください。曖昧さがある場合は、解釈が食い違わないよう明確な詳細を追加してください。バッチ分析ツールが報告した矛盾のある組み合わせごとに、resolve-spec-conflict スキルを使用して原因を特定し、処理を進める前に修正してください。
明確化(仕様ごと)
各機能仕様は曖昧さのないものにしてください。レンダラーが合理的に解釈できる方法は、1つだけである必要があります。仕様の記述だけでは動作を完全に明確化できない場合は、その下に - の箇条書きまたは文を追加してください。詳細は記述内容を明確にするものであり、別個の機能を追加するものではありません。詳細を含めても、仕様が示す実装規模は200 LOC以下でなければなりません。
***functional specs***
# send-message
A :User: can send a :Message: to a :Conversation:.
- A :Message: must have non-empty content.
- The :Message: is appended to the end of the :Conversation:.
- All :Participant: members of the :Conversation: can see the new :Message:.
決定論的なインターフェース
開発者が生成されたコードを読まなくても、ビルド済みのソフトウェアを利用できるよう、仕様を詳細に記述してください。すべての外部インターフェースを明示する必要があります。REST エンドポイントのパスと HTTP メソッド、CLI コマンド名と引数、ファイル形式、メッセージスキーマなどが該当します。インターフェースの詳細をレンダラーの判断に委ねてはなりません。
カプセル化
機能のすべてを仕様文の中で完結させてください。requires モジュールがインポートするのは機能仕様のみです。そのため、動作の説明を実装要件に頼らないでください。実装要件は下流のモジュールから参照できません。
テストシナリオ
バッチの挿入後、挿入した機能ごとに、順番に add-test-scenarios を1回実行してください。この処理により、各機能のテスト用プレーンファイル(慣例として tests/<module>/<func-id>.plain)が作成されます。モジュールで適合性テストが有効になっている場合、このファイルには少なくとも1つの適合性シナリオを含めてください。これは一括処理の一部ではなく、仕様ごとに実行してください。
アンチパターン
- バッチが「少ない」と感じるからといって、仕様ごとのチェックを省略しないでください。 仕様が2つだけでも、複雑度チェックを2回実施し、追加する両方の仕様を含めた競合チェックをバッチで実施する必要があります。
- ペアごとの競合分析に切り替えないでください。 追加する仕様ごとに、関連するすべての仕様をまとめて
analyze-func-specsで一度分析してください。すべてのペアに対してanalyze-2-func-specsを実行しないでください。 - 複雑度チェックをすべて先に実行し、競合チェックを最後にまとめて実行しないでください。 ワークフローの説明に従って、仕様ごとに交互に実行してください。そうしないと、先に複雑度チェックが失敗した場合、後続の競合チェックが無駄になります。
- すべての仕様を先に追加してから分析しないでください。 問題のある仕様がすでにファイル内にあると、以降の競合分析に影響します。
- 追加する仕様が「たくさん」あるからといって、手作業で作成しないでください。正しい対応は、分析の呼び出しを減らすことではなく、増やすことです。
- 仕様が1つだけの場合、このスキルを使用しないでください。
add-functional-specを使用してください。大量追加の管理作業を除けば、同じチェックを実行します。
検証チェックリスト
- バッチ内のすべての仕様で、コード変更が200行以下になることを確認済み(
analyze-if-func-spec-too-complexで検証) - 追加する仕様と既存の仕様との間に競合がないことを確認済み(
analyze-func-specsのバッチ呼び出しで検証) - バッチ内の追加する仕様同士に競合がないことを確認済み(同じ
analyze-func-specsのバッチ呼び出しで検証) - バッチ分析ツールが報告した競合するペアをすべて、バッチ完了前に
resolve-spec-conflictで解決済み - すべての仕様を言語に依存しない用語で記述済み(特定の言語やフレームワークに関する記述なし)
- すべての外部インターフェースを明示済み(エンドポイントパス、メソッド、CLI 引数、形式など)
- 参照する
:Concepts:がすべて***definitions***で定義済み - 文が短く、明確で、曖昧さがない
-
concise-specs.mdに従って、すべての仕様を簡潔化済み:自明な記述、根拠、検証不可能な形容詞や婉曲表現がなく、全体を平易な言葉で記述 - 既存の仕様やバッチ内の仕様との重複がない
- 仕様を正しい時系列の位置に配置済み
- すべての func-id が
semantic-ids.mdに従い、モジュール内およびバッチ内で一意 - 適合性テストが有効な場合、追加した機能ごとに
add-test-scenariosを呼び出し済み