specification-writing について
エージェントやメンテナーが自律的に実装を始められるよう、必要な背景をまとめる仕様書作成スキルです。現状と目標の明確化、根拠に基づく調査、未解決事項、意思決定の記録、仕様書のライフサイクルを扱います。
主な機能
- 01背景を重視した仕様書作成指針
- 02一文の主題とメンテナー向け要件
- 03根拠に基づく調査と意思決定の整理
- 04アーキテクチャや API 変更の記録
- 05実装計画と仕様書のライフサイクル
活用シーン
- 01自律実装に向けた機能仕様書の作成
- 02調査結果と未解決の設計事項の記録
- 03アーキテクチャや API 変更の計画
- 04実装完了後の仕様書の整理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ epicenterhq/ epicenter --skill specification-writingインストール後、Claude Code で/specification-writingを入力して読み込まれたか確認します。
同梱ファイルreferences/decision-hygiene.md
詳細
仕様書の作成
文章セクションではwriting-voiceに従ってください。所有権やフローを説明する際は、役立つモデルから始め、関連する境界に結び付け、実装に必要な図と文章だけを残してください。
仕様書は、エージェントやメンテナーが機能を自律的に実装するために必要な背景情報を示します。すべてを網羅的に説明することが目的ではありません。方向性に信頼性があると分かるだけの根拠を示し、実装担当者が具体的に着手できる状態にすることが目的です。
仕様書は作業中の足場であり、永続的な記録ではありません。 作業を計画し、作業中に調査結果を保持するためのものです。権威ある記録ではなく、作業終了後まで残るものでもありません。永続的な決定はdocs/adr/に、共有語彙はdocs/CONTEXT.mdに、現在の状態はdocs/reference/とコードに記録します。仕様書の作成中に重要な決定が固まったら、その場でdocs/adr/にProposed ADRとして記録し、仕様書から参照してください。後で「拾い上げる」ために仕様書の中に埋もれさせてはいけません。作業が完了したら、仕様書のライフサイクルに従って仕様書を整理してください。ADRの承認はADRガイダンスに従います。実装の完了を理由にステータスを変更してはいけません。履歴はGitとdocs/spec-history.mdで管理します。
注:このガイドでは、記入が必要な箇所を
[PLACEHOLDER]マーカーで示します。コードブロックはテンプレートです。角括弧で囲まれた内容を、機能の詳細に置き換えてください。
参考資料
仕様書で扱う判断事項に応じて、必要な資料を参照してください。
- トレードオフが多い場合、移行に伴う整理がある場合、または「一貫性を保つため」の判断がある場合は、references/decision-hygiene.mdを読んでください。
- アーキテクチャ、API、ライフサイクル、所有権に変更がある場合は、変更前後の例と視覚的な伝え方のリズムについて、../pull-request/references/body-patterns.mdを読んでください。
基本方針
仕様書では、次のことを心がけてください。
- 指示ではなく背景を示す:「なぜ」と「何を」を伝え、「どのように」は実装担当者に考えてもらいます
- 結論ではなく調査内容を記録する:何を調べたか、何が存在するか、何が存在しないかを示します
- 問いを未解決のまま残す:「未解決の質問」セクションは欠点ではなく、仕様書の重要な要素です
- 自律的な実装を可能にする:これを読むエージェントが、検証や調査の拡張のためにサブエージェントを起動できるようにします
- メンテナーの時間を尊重する:読者に履歴、付録、実装ログを読ませる前に、現在の作業経路が分かるようにします
- プロセスの形骸化を避ける:テンプレートにあるからではなく、実装やレビューに影響する場合にセクションを設けます
良い仕様書は、従うべき台本ではなく、作業の出発点です。
セクションの概要を作る前に、one-sentence-testを適用してください。この仕様書が何についてのものかを、具体的な一文で言えないなら、設計はまだ一貫していません。それが明らかになった点であり、仕様書はまだ完成していません。
メンテナーの時間に関する要件
仕様書の最初の画面で、次のことに答えられるようにしてください。
What is this?
Is it active, implemented, superseded, or historical?
What is the current shape?
What is the target shape?
What proves the change is done?
大規模な仕様書でもかまいません。作業が複雑であれば、詳しく記述することは有用です。「N行を超えたら分割する」というルールではありません。ある読者の作業が、別の読者の作業を妨げないようにすることが重要です。
1つの文書に次の内容が混在する場合は、分割するか、作業にすぐ着手できる短いセクションを追加してください。
- 全体的なアーキテクチャと具体的な実行手順。
- 過去の議論と現在の実装経路。
- 仕様書の内容と引き継ぎ用プロンプト。
- 作業の開始には不要だが、役立つ付録や台帳。
すべてを1つのファイルにまとめる場合は、冒頭近くに「この仕様書の読み方」ブロックを追加してください。
Read first:
One Sentence
Current State
Target Shape
Implementation Plan
Verification
Read if changing the architecture:
Design Decisions
Rejected Alternatives
Edge Cases
Historical only:
Implementation Notes
Superseded Decisions
Execution Prompts
読者が1分で現在の事実を、5分でモデルを、15分で実行経路を把握できるようにしてください。
仕様の配置
実装仕様はすべてルートの /specs/ に配置します。apps/ や packages/ の下にネストした仕様を作成しないでください。
新しい仕様には specs/YYYYMMDDThhmmss-feature-name.md という名前を付けます。ローカルのタイムスタンプと、ケバブケースの機能名を使用します。
プロンプトや引き継ぎ用の成果物は、.prompt.md、.handoff.md、.execute.md のような明示的なサフィックスを付けて、仕様の隣に配置できます。これらは正規の仕様へのリンクを含める必要があり、サフィックスにそう示されていない限り、現在の実装計画として扱わないでください。
意思決定の整理
重要な意思決定はすべて分類します。
| 分類 | 解決方法 | ルール |
|---|---|---|
| 1 | 根拠 | ソース、テスト、またはバージョン確認で検証します。 |
| 2 | 設計の一貫性 | 仕様の基本方針を一貫して適用します。 |
| 3 | 制約下での好み | 意図的に選択し、その制約を記録します。 |
何かを「維持する」と決める前に、「それがまだ存在していなかったとして、これを追加するか?」と考えてください。
- 追加する場合は、ユースケースを記録します。
- 追加はしないものの、削除による変更量が多い場合は、Decision Log に分類 3 の維持判断として記録します。
- 追加せず、削除も簡単な場合は、今すぐ削除します。
根拠に関する疑問を設計の一貫性の陰に隠さないでください。古いパスを削除する前に検証します。例や失敗パターンについては、references/decision-hygiene.md を読んでください。
ドキュメント構成
すべての仕様にすべてのセクションが必要なわけではありません。小さな機能なら Research Findings を省略してもかまいません。移行仕様なら Edge Cases に重点を置くこともできます。状況に応じて判断してください。
ヘッダー(必須)
# [Feature Name]
**Date**: [YYYY-MM-DD]
**Status**: Draft | In Progress
**Owner**: [Name/team responsible for decisions]
**Branch**: [optional: branch name if work has started]
**Supersedes**: [optional: previous spec paths]
**Superseded by**: [optional: later spec path]
一文
すべての仕様には、概要の前に具体的な一文が必要です。これはメンテナーの指針となる一文です。
## One Sentence
[One sentence naming the new shape and the boundary it changes.]
概要
最大1段落で、機能の内容を説明します。宣伝はしないでください。
## Overview
[One to two sentences describing what this feature adds or changes and what it enables. Be specific about the capability, not vague about benefits.]
動機
現状、問題、目指す状態の順に構成します。
## Motivation
### Current State
[Show actual code or configuration demonstrating how things work TODAY. Use real code blocks, not prose descriptions.]
This creates problems:
1. **[Problem Title]**: [Specific explanation of what breaks or is painful]
2. **[Problem Title]**: [Specific explanation of what breaks or is painful]
### Desired State
[Brief description of what the target looks like. Can include a code snippet showing the ideal API or structure.]
調査結果
仕様の価値が発揮されるセクションです。推測したことではなく、実際に見つけたことを記録します。
## Research Findings
### [Topic Researched]
[Description of what you investigated and methodology]
| [Category] | [Dimension 1] | [Dimension 2] |
| ------------- | -------------- | ---------------- |
| [Project/Lib] | [What they do] | [Their approach] |
| [Project/Lib] | [What they do] | [Their approach] |
**Key finding**: [Your main discovery, for example that no standard exists, or that everyone does X]
**Implication**: [What this means for your design decisions]
以下を含めます。
- 類似プロジェクトの実装(比較表)
- 検索したものの見つからなかった内容(「確立されたパターンは存在しない」)
- 参照したドキュメントへのリンクや参考資料
設計上の決定
追跡可能性を確保するため、表を使用します。重要な決定にはそれぞれ分類と根拠が必要です。
根幹を支える決定(分類 2 の一貫性に関する判断、またはアーキテクチャ、所有権、API の形状、再検討する必要がないほど十分に検討した却下案に関する分類 3 の好みの判断)は、この表だけでなく ADR に記録します。決定が固まった時点で、docs/adr/ に Proposed の ADR として記述し、表の根拠欄に ADR 番号を記載します。こうすることで、この表から仕様上の決定を長期的に参照できる場所へたどれるようになります。仕様が削除された後も、ADR は残ります。
## Design Decisions
| Decision | Class | Choice | Rationale |
| ------------------- | ----------- | ---------------- | ------------------------------- |
| [Decision point] | 1 evidence | [What you chose] | [Source, test, or version checked] |
| [Decision point] | 2 coherence | [What you chose] | [How this follows the thesis] |
| [Decision point] | 3 taste | [What you chose] | [Constraint and trade-off] |
| [Deferred decision] | Deferred | Deferred | [Why it is deferred and what would bring it back] |
アーキテクチャ
文章より図を優先します。フェンス付きテキスト図、ファイルツリー、ルート表、変更前後のブロックを使用してください。デフォルトでは、すばやく書けて編集しやすいシンプルな ASCII 図を使います。整った図にする価値が追加の手間を上回る場合にのみ、罫線素片文字を使用します。
## Architecture
[Describe what the diagram shows]
[caller]
-> [boundary or route]
-> [policy or validation]
-> [storage or primitive]
複数のステップからなるフローの場合:
Step 1: [Step name]
[What happens in this step]
Step 2: [Step name]
[What happens in this step]
カタログ(プリミティブのセットを導入する場合)
仕様で一貫性のある新しいプリミティブのセット(列の種類、アクションのバリエーション、エラーの種類、修飾メソッドなど)を導入する場合は、それらをカタログとして提示します。すべてのプリミティブと一行の注釈を一覧にした簡潔なコードブロックを記載し、詳しい説明が必要なものだけ、後続のセクションで詳述します。
カタログを使うと、読者は個々のプリミティブを詳しく見る前に、全体の範囲をひと目で確認できます。
## The field.* catalog
```ts
field.string<TBrand?>(s?) // TEXT (TBrand for branded strings)
field.number(s?) // REAL
field.integer(s?) // INTEGER
field.boolean() // INTEGER 0/1
field.select([value]) // TEXT (single-element set)
field.select([...]) // TEXT + CHECK constraint
field.json<S extends TSchema>(schema) // TEXT JSON-encoded, schema required
nullable(inner) // Type.Union([inner, Type.Null()]) (standalone)
field.datetime(s?) // RFC 3339 string, branded DateTimeString
field.string<IanaTimeZone>() // IANA zone string, branded IanaTimeZone
```
Every primitive justified by N+ existing call sites in the audit.
### What was considered and rejected
| Candidate | Why rejected |
|---|---|
| `field.id()` | Subsumed by `field.string<IdBrand>()` + a co-located `generate*` factory |
| `field.array(of)` | Subsumed by `field.json(Type.Array(of))` |
| Declaring `_v` as a column | Library-managed; positional in `defineTable(v1, v2, ...)` |
カタログと同じくらい、「却下した候補」の表も役立つことがよくあります。実装者に追加すべきでないものと、その理由を示せます。これにより読者は、扱う範囲が適切に絞られていると確信できます。
呼び出し箇所(実際のコードにおける変更前/変更後)
仕様によって利用者向け API が変更される場合、実際の呼び出し箇所を少なくとも 2~3 件翻訳して示してください。作り物の例は使わないでください。実際のコードを確認することで、抽象的な提案では見落とされる意味上の変化が明らかになります。
まずコードベース内の実際の使用箇所を探してください。「変更前」はファイル名と行番号を添えてそのまま示し、続けて「変更後」の形を示します。自明でない対応関係には、簡潔なコメントを付けてください。
## Call sites: before and after
### honeycrisp notes table
**Before** (`apps/honeycrisp/src/lib/workspace.ts:78`):
```ts
const notesTable = defineTable(
type({ id: NoteId, title: 'string', _v: '1' }),
type({ id: NoteId, title: 'string', wordCount: 'number | undefined', _v: '2' }),
).migrate(...)
```
**After**:
```ts
const notesTable = defineTable(
{ id: field.string<NoteId>(), title: field.string() },
{
id: field.string<NoteId>(),
title: field.string(),
wordCount: nullable(field.number()),
},
).migrate(({ value, version }) => {
switch (version) {
case 1: return { ...value, wordCount: null };
case 2: return value;
}
});
```
**Semantic shift to flag**: rows previously stored with `wordCount` key absent will now read as `null` instead of `undefined`. Affects app code doing `if (row.wordCount === undefined)`. Also: `_v` no longer appears in the column record; it is library-managed and stripped from returned rows.
「指摘すべき意味上の変化」のコールアウトは重要です。実装担当者がコードベース全体で検索し、コードモッドを適用するために必要な情報です。
実装計画
フェーズに分けてください。進捗管理にはチェックボックスを使います。フェーズ 1 は詳細に記述し、それ以降のフェーズは大まかな記述で構いません(実装担当者が具体化します)。
## Implementation Plan
### Phase 1: [Phase Name]
- [ ] **1.1** [Specific, atomic task]
- [ ] **1.2** [Specific, atomic task]
- [ ] **1.3** [Specific, atomic task]
### Phase 2: [Phase Name]
- [ ] **2.1** [Higher-level task the implementer will break down]
- [ ] **2.2** [Higher-level task]
切れ目のない変更のためのフェーズ順序:構築、検証、削除
仕様で古いコードパスを置き換える場合は、利用者が新しいパスへ切り替える方法、置き換えが機能することを検証する方法、そして旧パスの廃止前に復旧できる方法を計画してください。分離可能な置き換えと分離不可能な置き換えについては、rethink の切れ目のない変更に関するリファレンスを参照してください。固定のフェーズ数を押し付けるのではなく、依存関係に応じてフェーズを決めてください。
エッジケース
前提を崩す可能性があるシナリオや、特別な対応が必要なシナリオを列挙してください。
## Edge Cases
### [Scenario Name]
1. [Initial condition]
2. [What happens]
3. [Expected outcome or "See Open Questions"]
### [Scenario Name]
1. [Initial condition]
2. [What happens]
3. [Expected outcome]
未解決の質問
このセクションは、実装担当者に「これはあなたが決めてください」と伝えるものです。推奨事項は含めますが、質問への結論は出さないでください。
## Open Questions
1. **[Question about an unresolved design decision]**
- Options: (a) [Option A], (b) [Option B], (c) [Option C]
- **Recommendation**: [Your suggestion and why, but explicitly leave it open]
2. **[Another unresolved question]**
- [Context about why this is uncertain]
- **Recommendation**: [Suggestion or "Defer until X"]
関連作業
ほとんどの仕様ではこのセクションは不要です。仕様は実行の指針であり、変更対象ファイルの許可リストではありません。関連作業が重要な場合は、実装担当者に必要なことだけを記載してください。つまり、先送りする項目(現時点では必須ではないが、後から実施してよいもの)と、機会があれば対応してよい項目(発見され、根拠がある場合に修正してよいもの)です。
## Adjacent Work
- [Decision or feature]: [Why it is not required now, and what would bring it back.]
- [Issue or cleanup]: [Why it is not required, but may be fixed if discovered and grounded.]
決定事項ログ
このセクションは、クラス 3 の維持項目にのみ使用してください。各項目には、制約と再検討のきっかけを明記してください。
## Decisions Log
- Keep `[name]`: [constraint or trade-off].
Revisit when: [specific signal that would make the keep decision worth re-opening].
成功基準
完了したことをどのように確認しますか?検証項目にはチェックボックスを使ってください。
## Success Criteria
- [ ] [Specific, verifiable outcome]
- [ ] [Specific, verifiable outcome]
- [ ] [Tests pass / build succeeds / docs updated]
参考資料
変更または参照するファイルです。
## References
- `[path/to/file.ts]` - [Why this file is relevant]
- `[path/to/pattern.ts]` - [Pattern to follow or reference]
仕様が細かく指示しすぎると、エージェントは盲目的に従います。曖昧すぎると、エージェントは行き詰まります。ちょうどよいのは、着手するのに十分なコンテキストがあり、実装を主体的に進められるだけの余地もある状態です。