write-product-spec について
Warp の重要な機能について、ユーザー視点の `PRODUCT.md` 仕様を作成するスキルです。観察可能な動作をテスト可能な不変条件として整理し、実装詳細は `TECH.md` に分けます。
主な機能
- 01ユーザー視点のプロダクト仕様作成
- 02テスト可能な動作不変条件の列挙
- 03エッジケースと状態の整理
- 04チケットまたは機能名による仕様パス
- 05`write-tech-spec` との連携
活用シーン
- 01実装前に期待動作を明確化
- 02UI、API、CLI 機能の要件記録
- 03技術仕様に先立つプロダクト仕様の作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ warpdotdev/ common-skills --skill write-product-specインストール後、Claude Code で/write-product-specを入力して読み込まれたか確認します。
詳細
write-product-spec
Warp の重要な機能について、PRODUCT.md 仕様書を作成します。
概要
プロダクト仕様書では、エージェントが機能を正しく実装し、リグレッションを回避できるよう、期待される動作を明確に記述します。機能はユーザーの視点だけから説明します。ユーザーが何を見て、何を行い、どのような体験をするか、またユーザーにとって維持されるべき不変条件を記述します。実装の詳細(内部型、状態の構成、モジュール境界、データフロー、アルゴリズム)は含めないでください。
「ユーザー」は Warp アプリのエンドユーザーに限りません。設計対象のインターフェースを利用する人やものを指します。
- UI/UX 機能の場合:Warp を使う人。
- データモデルの場合:そのモデルの読み書きを行うコード。
- API、プロトコル、ライブラリの場合:その API の呼び出し元(他のサービス、クライアントコード、プラグイン、エージェントなど)。
- CLI ツールや開発者向けインターフェースの場合:それを呼び出す開発者。
仕様書では、利用者の視点から動作を説明します。インターフェースの形状、実行できる操作、操作に対して返される内容、信頼できる不変条件、対処すべきエッジケースを記述し、内部での実装方法は指定しません。
実装の詳細、検証、テスト計画は、write-tech-spec スキルで作成する補足資料 TECH.md に記載します。プロダクト仕様書の作成は通常、2 段階のプロセスの最初のステップです。PRODUCT.md の合意後、同じ機能について TECH.md を作成するために write-tech-spec を実行してください(または、それが次のステップであることをユーザーに伝えてください)。プロダクト仕様書は、それを基にテック仕様書を直接作成できる内容にしてください。
仕様書は specs/<id>/PRODUCT.md に作成します。<id> には次のいずれかを指定します。
- Linear のチケット番号(例:
specs/APP-1234/PRODUCT.md) gh-を先頭に付けた GitHub issue の ID(例:specs/gh-4567/PRODUCT.md)- 短い kebab-case の機能名(例:
specs/vertical-tabs-hover-sidecar/PRODUCT.md)
specs/ の直下には、ID を名前とするディレクトリのみを置いてください。エンジニア名のサブディレクトリは作成しないでください。
チケット/issue への参照は任意です。ユーザーが Linear のチケットまたは GitHub issue を持っている場合は、その ID を使用してください。ない場合は、ディレクトリ名に使う機能名を尋ねてください。ユーザーから明示的に依頼された場合に限り、新しい Linear チケットまたは GitHub issue を作成してください。その場合は、それぞれ Linear MCP ツールまたは gh CLI を使用してください。チーム、ラベル、リポジトリが不明な場合は ask_user_question を使用してください。
作成前の確認事項
必要な情報だけを集めてください。ディレクトリ ID(Linear チケット、GitHub issue、または機能名)、機能の概要、対象ユーザー、主な動作、エッジケース、機能の検証方法を確認します。不足している情報を推測で補わず、ask_user_question を使用してユーザーに尋ねてください。
Figma モック
機能に UI やインタラクションのデザインが含まれる場合は、Behavior セクションの草案を作成する前に、Figma モックがあるかユーザーに尋ねてください。提供されたリンクは仕様書に含めてください。モックは、視覚状態、間隔、エッジケースのレイアウトに関する最も信頼できる情報源であることが多く、確認しないと、デザイナーがすでに決定した意図を Behavior セクションで推測してしまう可能性があります。
- リンクが提供された場合は、短い
## Figmaセクション内(または Behavior の冒頭付近)にFigma: <link>として含めてください。 - モックがないとユーザーが確認した場合は、その不在が曖昧にならないよう
Figma: none providedと記載してください。 - 機能が完全にバックエンドのみ(データモデル、API、視覚的なインターフェースを持たない CLI など)の場合は、質問を省略し、セクションも追加しないでください。
デザインに関するコンテキストを黙って省略しないでください。通常デザインの確認が必要となる機能では、何も記載しないより「なし」と明記するほうが望ましいです。
構成
必須セクション:
- 概要 — 機能と目指す結果を説明する1〜3文。
- 動作 — 仕様の中心となる部分です。この機能の動作を、網羅的な英文で、テスト可能な不変条件として番号付きで記述します。詳細は下記の「動作セクション」を参照してください。仕様としての価値を生むのはここであり、重複を避けるため、それ以外の内容は簡潔にします。
任意のセクション — 中核となる内容以上の情報を加える場合にのみ含めます。内容がない場合は見出しごと省略し、プレースホルダーとして「なし」と書かないでください。
- 課題 — 概要から動機が明らかでない場合にのみ含めます。
- 目標/非目標 — スコープが曖昧な場合、または議論が分かれている場合に含めます。
- Figma — リンクがある場合はリンクを含めます。デザインが重要でモックがない場合は、
Figma: none providedと明記します。ビジュアルを伴わない機能では完全に省略します。上記の「Figma モック」を参照してください。 - 未解決の質問 — 関連する動作の近くに
**未解決の質問:** …とインラインで記載するのを優先します。未解決の質問が複数あり、まとめる価値がある場合にのみ、専用セクションを設けます。
検証、成功基準、テストのセクションは含めないでください。検証とテスト計画は、write-tech-spec によって作成される付属の TECH.md に記載します。動作は、単独でテスト可能な番号付きの不変条件として記述します。技術仕様から直接参照できるようにしてください。
動作セクション
動作が仕様の本体です。それ以外は枠組みにすぎません。
動作の目標は、この機能の動作を完全に英文で記述し、執筆者が推測したり、プロダクトの意図を再導出したりせずに技術仕様を直接作成できるだけの詳細を盛り込むことです。動作を読み終えた読者に、ある状況でこの機能がどう動くのかという疑問が残るなら、そのセクションは未完成です。
最低限、以下を記述します。
- デフォルトの動作と、想定されるユーザーフロー。
- ユーザーに表示されるすべての状態と、それらの遷移。
- ユーザーが指定できるすべての入力と、それに対する機能の応答。
- 空の状態、エラー状態、読み込み中/保留中の状態、キャンセル。
- 合理的な実装者でも確認しない可能性のあるエッジケース。権限拒否、オフライン、タイムアウト、状態変更の競合、複数インスタンスの同時実行、古いデータや欠落データ、操作の途中でフォーカスが失われる場合、隣接する機能との相互作用など。
- 関連する場合は、キーボード操作、アクセシビリティ、フォーカスに関する要件。
- 常に維持されるべき不変条件と、リグレッションしてはならない動作。
動作の長さは機能に合わせてください。単純な機能なら数個の不変条件で済むこともあります。複雑な機能では多数の条件が必要になり、フローや状態ごとにサブセクションを設けることもあります。仕様全体が肥大化しないよう、動作を必要なだけ網羅的に記述できるように、それ以外の部分は簡潔にします。エッジケースは、少なくするよりも一つ多く列挙する方を選んでください。
長さの目安
動作は機能に必要な長さにしてください。行数の目標に合わせるためにエッジケースを省略しないでください。以下の目安は、動作以外(概要、任意のセクション)に適用されます。仕様全体の長さが構成上の負担ではなく、機能の実際の複雑さを反映するよう、これらの説明は簡潔にしてください。
- 軽微な修正や狭い範囲の UI 調整:仕様書は不要です。
- 小規模な機能(単一モジュール、エッジケースが少数):枠組みと動作を合わせて通常約30〜60行です。
- 中規模な機能(複数モジュール、複数の状態):通常約80〜150行です。
- 大規模な機能、または動作が複雑な機能:さらに長くても問題ありません。長さの大部分は動作に割り当ててください。
概要、課題、目標、動作で同じ内容を繰り返している場合は、動作の内容ではなく、枠組みを簡潔にしてください。
作成のガイドライン
- 意欲的な表現より、具体的で観察可能な動作を優先してください。
- 可能な場合、動作は文章ではなく不変条件のリストとして記述してください。
- 後退させてはならない不変条件や、見落としやすいエッジケースを記録してください。
- UX に不可欠な場合を除き、実装の詳細は避けてください。
- 各セクションには設ける価値が必要です。他のセクションと重複する、または定型文だけになるセクションは省略してください。
仕様を最新の状態に保つ
承認済みの仕様は、実装と同じ PR でリリースされることがあります。実装の進展に伴い、ユーザー向けの動作や UX の詳細が変わった場合は、同じ PR で PRODUCT.md を更新してください。チェックインされた仕様には、実際にリリースされる機能を記述する必要があります。
大規模な機能の場合、実装担当者は設計および実装時に決定した具体的な事項をまとめた DECISIONS.md ファイルを任意で作成できます。今後のエージェントに役立つ場合は作成し、そうでなければ省略してください。
関連スキル
implement-specswrite-tech-specspec-driven-implementation
動作セクションの例
仮想機能である Warp のブロックリストにおける GitHub Flavored Markdown テーブルのレンダリングを例に、動作セクションのサンプルを示します。期待される形式として、デフォルト、エッジケース、不正な入力、ストリーミング、選択とコピー、検索、共有、テーマ設定、各画面間の一貫性を列挙する、番号付きのテスト可能なユーザー視点の不変条件を示し、インラインの未解決の質問を 1 つ含めています。
## Behavior
1. When a terminal output block contains a GitHub-flavored Markdown table (a header row, a separator row of one or more `---` segments, and one or more body rows, all delimited by `|`), that table renders as a visually formatted table in the block — not as raw pipe-delimited text.
2. The table renders with:
- A visually distinct header row.
- Aligned columns based on the separator row: `|:---|` left-align, `|:---:|` center, `|---:|` right-align. `|---|` with no colons falls back to the default alignment (left for text, right for numeric-looking values).
- Visible row separators (or equivalent spacing) consistent with the active theme.
3. Inline markdown inside a cell renders inline: bold, italic, inline code, strikethrough, and links all render the same way they do in the surrounding block output. Line breaks inside a cell (`<br>` or escaped `\n`) render as in-cell line breaks.
4. Column widths are chosen to fit the table's natural content when it fits inside the block. If a single cell's content is very long, that cell wraps its text within its column rather than forcing the column to an unreasonable width.
- **Open question:** when a wrapped cell would produce an unreasonably tall row, do we clip with an "expand" affordance, or let the row grow unbounded?
5. Horizontal scrolling: when the table's total width exceeds the block width — many columns, or wide columns that can't reasonably be narrowed — the table becomes horizontally scrollable within the block. Scrolling horizontally reveals off-screen columns without clipping or truncating them. Vertical scrolling of the block continues to work independently of table scroll.
6. When the block is resized (terminal resize, pane split, sidebar open/close), the table reflows to the new width without losing row or column order.
7. Empty cells render as visibly empty (same row height as surrounding cells, no placeholder text). A row with all empty cells still renders as a row.
8. A table with only a header and separator (zero body rows) renders as a header-only table, not as raw text.
9. A single-column table renders as a single-column table (not collapsed to a bullet list or similar).
10. Malformed tables fall back gracefully:
- Missing separator row → rendered as preformatted text, not as a table.
- Ragged rows (some rows have fewer or more cells than the header) → missing cells render empty; extra cells are shown, with the header row extended visually if possible. The block should never silently drop data.
- Unclosed table (last row truncated mid-stream) → rendered as a partial table; see (11).
11. Streaming output: while a command is still producing rows, the table renders incrementally. New rows append as they arrive. The header row locks in as soon as the separator line is received; rows before the separator render as plain text until the table is recognized.
12. Selection and copy:
- Selecting across cells with the mouse or keyboard selects their visible text content.
- Copying the selection produces tab-separated plain text by default (one row per line, cells separated by tabs). An affordance (context menu, shortcut) lets the user copy the original markdown source instead.
- Copying the entire block preserves the original markdown source verbatim.
13. Search within a block (find-in-block) matches against cell text content. Matches highlight in place in the rendered cell; navigating matches scrolls the table into view, including horizontally if the match is in an off-screen column.
14. Sharing or exporting a block (Warp Drive, share link, save as file) preserves the original markdown source, not the rendered form.
15. Theming: table borders, header backgrounds, alternating row shading (if any), and link/code styles all come from the active Warp theme. No hard-coded colors.
16. Markdown tables render consistently wherever block-list markdown already renders — command output, agent responses, and any other block type that supports inline markdown. The same input produces the same table in each surface.
17. Non-table pipe content is not misrendered as a table. Text that contains `|` characters but no valid header-separator line remains plain text, even if it visually resembles a table.