add-functional-spec について
add-functional-specは、.plain モジュールに機能仕様を1件追加するスキルです。複雑さ、競合、明確さ、順序、任意の適合テストを確認します。
主な機能
- 01仕様の作成と簡潔化
- 02複雑さの上限確認
- 03一括での競合分析
- 04外部インターフェースの明示
- 05適合テストの追加
活用シーン
- 01機能要件を1件追加
- 02既存の動作との競合確認
- 03仕様のテストシナリオ作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ plainlang/ plain-forge --skill add-functional-specインストール後、Claude Code で/add-functional-specを入力して読み込まれたか確認します。
詳細
機能仕様の追加
まずルールを読み込んでください。 .plain ファイルを読む、編集する、または書き込む前に、load-plain-reference スキルを呼び出し、案内されたルールファイルを読んでください。この会話ですでに load-plain-reference が実行されている場合に限り、省略できます。
ワークフロー
- 対象の
.plainファイルを特定します。 曖昧な場合は、ユーザーに確認してください。 - ファイル全体を読みます。 既存の定義、実装要件、現在の機能仕様(
requiresモジュール内のものも含む)をすべて把握してください。 - func-id を選び、機能仕様を作成します。
semantic-ids.mdに従って func-id を選び、その ID の# <func-id>見出しがモジュール内に存在しないことを確認してください。以下のルールに従って、本文、記述行、およびその下に置く詳細を作成し、ドラフトに対してconcise-specs.mdのレビュー手順を実行してください。ほかの確認を行う前に、すべての事実を保ったまま、文面を最短に整えてください。 - 複雑さを分析します。
analyze-if-func-spec-too-complexスキルを使って、ドラフトした仕様が 200 LOC 以下を想定していることを確認してください。複雑すぎる場合は、break-down-func-specスキルを使って分割し、分割後の各仕様についてステップ 3 から繰り返してください。 - 競合を確認します。 既存のすべての機能仕様との競合を確認してください。これは非常に重要です。新しい仕様と、ファイル内および
requiresの依存関係全体にある既存のすべての仕様をまとめて、analyze-func-specsを一度だけ実行してください。一括分析ツールは、競合するすべてのペアを一度の呼び出しで返します。ペアごとの分析ツールは呼び出さないでください。報告された競合ペアごとに、そのペアに対してresolve-spec-conflictを実行してください。解決のたびに、対象範囲を更新してanalyze-func-specsを再実行し、判定がCOMPATIBLEになるまで続けてください。 - 仕様を追加します。
***functional specs***セクションの末尾に、# <func-id>見出しと本文を追加してください。直前の機能仕様との間には空行を 1 行入れます(仕様は時系列順に並び、新しい仕様は最後に置きます)。 - ファイルをもう一度読みます。 配置と構文が正しいことを確認してください。
- テスト用の plain ファイルを書きます。 モジュールで適合性テストが有効になっている場合は、新しい機能について
add-test-scenariosを呼び出してください(下記の テストシナリオ を参照)。
ルール
複雑さの上限
各機能仕様が想定する変更コード行数は、最大 200 行です。要件が大きすぎる場合は、break-down-func-spec スキルを使い、互いに独立した複数の小さな仕様に分割してください。仕様の本文に LOC の見積もりを含めないでください。
時系列順
仕様は上から順に段階的にレンダリングされます。レンダラーは将来の仕様を認識しません。その時点で参照できるのは、それ以前にレンダリングされた仕様だけです。つまり、
- 新しい仕様では、以前の仕様で定義された振る舞いを参照できます。
- 新しい仕様では、後続の仕様が存在することを前提にできません。
- 後続の仕様より前に置く必要がある場合は、適切な位置に配置してください。それ以外の場合は末尾に追加します。
言語に依存しない記述
実装上の構造ではなく、振る舞い、概念、ドメインロジックの観点で記述してください。言語固有の型、ジェネリクス構文、フレームワークのアノテーション、その他の特定の言語やフレームワークに結び付いた構造は避けてください。null 値、JSON 型、HTTP ステータスコードなどの一般的な技術用語は使用できます。言語固有の指針は ***implementation reqs*** に記載してください。
競合なし
新しい仕様が既存の機能仕様と矛盾しないようにしてください。仕様の競合は、最も大きな損失につながります。追加前に既存の仕様をすべて確認し、新しい仕様との互換性を確かめてください。analyze-func-specs を使って、新しい仕様と既存のすべての仕様を一括で確認してください。競合するペアはすべて一覧表示されるため、ペアごとの分析は不要です。解釈に曖昧さがある場合は、競合する解釈を排除するための詳細を明記してください。一括分析で報告された競合ペアごとに、resolve-spec-conflict スキルを使って、先に問題を診断して解決してください。
曖昧さの解消
各機能仕様は曖昧さのないものにしてください。レンダラーが合理的に解釈できる方法は1つだけである必要があります。ステートメントの行だけでは動作を完全に明確にできない場合は、その下に - の箇条書きまたは文を追加してください。詳細はステートメントを明確にするものであり、独立した機能を追加するものではありません。詳細を加えた場合でも、仕様が示すコード量は200行以下でなければなりません。
***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 を実行してください。これにより、その機能のテスト用プレーンファイル(慣例では tests/<module>/<func-id>.plain)が作成されます。モジュールで適合性テストが有効になっている場合、このファイルには少なくとも1つの適合シナリオを記述してください。
検証チェックリスト
- 仕様が示すコード変更は200行以下
- 既存の機能仕様と矛盾しない
- 言語に依存しない用語で記述されている(特定の言語やフレームワークに依存しない)
- すべての外部インターフェース(エンドポイントのパス、メソッド、CLI引数、形式など)が明示されている
- 参照されている
:Concepts:がすべて***definitions***で定義されている - 文が短く、明確で、曖昧さがない
-
concise-specs.mdに従って簡潔化されている:自明な内容、根拠、検証できない形容詞や婉曲表現がなく、全体を通して平易な言葉が使われている - 既存の仕様と重複していない
- 正しい時系列上の位置に配置されている(通常は末尾)
- func-id が
semantic-ids.mdに従い、モジュール内で一意である - モジュールで適合性テストが有効になっている場合、新しい機能に対して
add-test-scenariosが実行されている