| name | spec-writing-patterns |
| description | Patterns for writing effective specs that capture user intent, design decisions, and requirements clearly. Use when creating or updating specs to ensure quality and completeness. |
Spec Writing Patterns
Guidelines for writing specs that effectively capture user intent and survive across sessions.
When to Use
- Creating a new spec
- Reviewing spec quality
- Refactoring unclear specs
- Teaching spec-writing practices
Spec Quality Principles
1. Capture WHY, Not Just WHAT
Specs should explain the motivation, not just list features.
❌ BAD: "Add user authentication"
✅ GOOD: "Users need to authenticate to access personalized content
and protect their data. Currently, all users see the same content
and there's no way to save preferences."
2. Self-Contained Context
A spec should be understandable without reading the entire conversation history.
❌ BAD: "As discussed, implement the thing we talked about"
✅ GOOD: "Implement rate limiting for the API to prevent abuse.
Context: We observed 10x normal traffic from a single IP causing
degraded performance for other users."
3. Clear Success Criteria
Define what "done" looks like with measurable outcomes.
❌ BAD: "Make it fast"
✅ GOOD: "Success Criteria:
- [ ] API response time < 200ms at p95
- [ ] Page load time < 2s on 3G connection
- [ ] Lighthouse performance score > 90"
4. Appropriate Granularity
Not too broad (epic), not too narrow (task).
❌ TOO BROAD: "Build the entire e-commerce platform"
❌ TOO NARROW: "Add padding to the submit button"
✅ JUST RIGHT: "Implement shopping cart functionality with
add/remove items, quantity updates, and persistent storage"
Spec Types
Feature Spec
Purpose: Define a new capability or feature.
Template:
# [Feature Name]
## Context
[Why this feature is needed, what problem it solves]
## User Stories
- As a [role], I want to [action] so that [benefit]
## Requirements
### Must Have
- [ ] Requirement 1
- [ ] Requirement 2
### Nice to Have
- [ ] Optional requirement
## Technical Considerations
[Architecture notes, constraints, dependencies]
## Success Criteria
- [ ] Measurable outcome 1
- [ ] Measurable outcome 2
## Out of Scope
[Explicitly state what this spec does NOT cover]
Example:
# Semantic Search for Markets
## Context
Users struggle to find relevant markets using keyword search.
They often don't know the exact terms used in market titles.
Semantic search will match intent, not just keywords.
## User Stories
- As a trader, I want to search using natural language
so that I can find markets even without exact keywords
## Requirements
### Must Have
- [ ] Vector embeddings for market descriptions
- [ ] Similarity search with configurable threshold
- [ ] Fallback to keyword search if vector search fails
### Nice to Have
- [ ] Search result explanations ("matched because...")
## Technical Considerations
- Use OpenAI embeddings (1536 dimensions)
- Store vectors in Redis with HNSW index
- Fallback to PostgreSQL trigram search
## Success Criteria
- [ ] 80% of test queries return relevant results in top 5
- [ ] Search latency < 500ms at p95
- [ ] Graceful degradation when Redis unavailable
## Out of Scope
- Multi-language support (future spec)
- Search history/suggestions (separate feature)
Design Decision Spec
Purpose: Document an architectural or technical decision.
Template:
# [Decision Title]
## Status
[Proposed | Accepted | Deprecated | Superseded by [[s-xxxx]]]
## Context
[What situation prompted this decision?]
## Decision
[What was decided?]
## Options Considered
### Option A: [Name]
**Pros:** [advantages]
**Cons:** [disadvantages]
### Option B: [Name]
**Pros:** [advantages]
**Cons:** [disadvantages]
## Rationale
[Why this option was chosen]
## Consequences
[What changes as a result of this decision?]
## References
- [[s-xxxx]] Related spec
- [External link](url)
Example:
# State Management Approach
## Status
Accepted
## Context
The application has grown complex state that's shared across
many components. Props drilling is becoming unwieldy.
## Decision
Use Zustand for global state management.
## Options Considered
### Option A: Redux
**Pros:** Industry standard, great devtools, middleware ecosystem
**Cons:** Boilerplate heavy, steep learning curve, overkill for our size
### Option B: Zustand
**Pros:** Minimal boilerplate, TypeScript-first, easy to learn
**Cons:** Smaller ecosystem, less middleware options
### Option C: React Context + useReducer
**Pros:** No dependencies, built into React
**Cons:** Performance issues with frequent updates, no devtools
## Rationale
Zustand provides the right balance of simplicity and power for
our current scale. The minimal API reduces onboarding time for
new developers, and TypeScript support is excellent.
## Consequences
- All shared state moves to Zustand stores
- Components use hooks to access state
- DevTools extension recommended for debugging
Research/RFC Spec
Purpose: Explore a problem space or propose a significant change.
Template:
# [RFC: Topic]
## Summary
[One paragraph overview]
## Motivation
[Why is this change needed?]
## Current State
[How things work today]
## Proposed Solution
[Detailed description of the proposal]
## Alternatives Considered
[Other approaches and why they weren't chosen]
## Migration Path
[How to get from current state to proposed state]
## Open Questions
- [ ] Question 1
- [ ] Question 2
## References
- Related work
- Prior art
Bug/Issue Spec
Purpose: Document a problem that needs investigation or fixing.
Template:
# [Bug Title]
## Observed Behavior
[What's happening]
## Expected Behavior
[What should happen]
## Reproduction Steps
1. Step 1
2. Step 2
3. Step 3
## Environment
- Browser/OS:
- Version:
- User type:
## Impact
[Who is affected, how severely]
## Suspected Cause
[If known, what might be causing this]
## Related
- [[i-xxxx]] Fix issue
- [[s-xxxx]] Related feature
Hierarchy Patterns
When to Use Parent/Child Specs
Use hierarchy when:
- Feature has multiple distinct subsystems
- Natural abstraction levels exist
- Different teams/agents will work on different parts
Don't use hierarchy when:
- Spec is already atomic
- Hierarchy would be only one level deep
- Relationships are peer-to-peer (use
related links instead)
Hierarchy Example
s-auth: Authentication System (parent)
├── s-oauth: OAuth Integration (child)
│ └── Requirements for Google, GitHub OAuth
├── s-sessions: Session Management (child)
│ └── Token storage, refresh, expiry
└── s-permissions: Permission System (child)
└── Roles, capabilities, access control
Creating Hierarchy
1. Create parent spec first
2. Create child specs with parent= parameter
3. Child specs inherit context from parent
4. Cross-reference: [[s-parent]] in children, [[s-child]] in parent
Cross-Referencing
Obsidian-Style Links
Basic reference:
See [[s-8h2k]] for authentication requirements.
With display text:
Implement per [[s-8h2k|auth spec]] guidelines.
With relationship:
Depends on [[s-9j3m]]{ blocks } completing first.
Reference issues:
Tracked in [[i-x7k9]] for implementation.
When to Reference
- Specs → Specs: Related requirements, dependencies
- Specs → Issues: Implementation tracking
- In prose: Inline context for readers
Anti-Patterns
Vague Requirements
❌ BAD:
"The system should be fast and user-friendly."
✅ GOOD:
"Requirements:
- Page load < 2s on 3G
- All interactive elements have loading states
- Error messages explain how to fix the issue"
Implementation Details in Specs
❌ BAD:
"Use React.memo on the MarketCard component and implement
virtual scrolling with react-window."
✅ GOOD:
"Requirements:
- Market list should handle 1000+ items smoothly
- No visible lag when scrolling
Technical Notes:
- Consider virtualization for large lists
- Profile before optimizing"
Missing Context
❌ BAD:
"Add the feature John requested in the meeting."
✅ GOOD:
"Add bulk export functionality for market data.
Context: Analysts need to export market data to Excel
for offline analysis. Currently they copy/paste manually."
Scope Creep in Single Spec
❌ BAD:
"Implement authentication, user profiles, social features,
notifications, and admin dashboard."
✅ GOOD:
Create separate specs:
- [[s-auth]] Authentication
- [[s-profiles]] User Profiles
- [[s-social]] Social Features
- [[s-notifications]] Notifications
- [[s-admin]] Admin Dashboard
With parent spec:
- [[s-user-system]] User System (parent of all above)
No Success Criteria
❌ BAD:
"Improve search functionality."
✅ GOOD:
"Improve search functionality.
Success Criteria:
- [ ] Relevant results in top 5 for 80% of test queries
- [ ] Search suggestions appear after 2 characters
- [ ] Recent searches shown on focus
- [ ] No results state shows helpful alternatives"
Quality Checklist
Before finalizing a spec, verify:
□ Context explains WHY (motivation clear)
□ Requirements are specific and measurable
□ Success criteria are defined
□ Scope is appropriate (not too broad/narrow)
□ Out of scope is explicit (if needed)
□ Cross-references link to related specs/issues
□ No implementation details (unless Technical Notes section)
□ Self-contained (readable without conversation history)
□ Hierarchy used appropriately (if complex)
Quick Templates
Minimal Feature Spec
# [Feature]
## Why
[One paragraph motivation]
## Requirements
- [ ] Must have 1
- [ ] Must have 2
## Success Criteria
- [ ] Measurable outcome
Minimal Decision Spec
# [Decision]
## Context
[Situation]
## Decision
[What we decided]
## Rationale
[Why]
Remember: Specs are for humans (and AI agents) to understand intent. Write them to be read months later by someone with no context. If a spec needs the original conversation to make sense, it needs more context.