Skill: Ralph Specs
Work with feature specifications in a codebase.
Overview
Specs describe what a feature is and why it exists. They are durable documents that outlive implementation details. Specs are not code — they link to code.
Plans are separate — they live in plans/ and track task execution. See the ralph-plan skill for that schema.
Related Skills
- •ralph-plan — Task execution and lifecycle
- •ralph-spec-to-plan — Generate plans from specs
Structure
specs/
├── INDEX.md # Lookup table for all features
├── feature-a/
│ ├── SPEC.md # Feature spec
│ └── sub-feature/
│ └── SPEC.md # Sub-feature spec
└── feature-b/
└── SPEC.md
plans/
├── pending/ # Plans not yet started
│ └── feature-a.md
├── current/ # Plans in active development
│ └── feature-b.md
└── complete/ # Finished plans (archive)
└── feature-c.md
Conventions:
- •One folder per feature in
specs/ - •
SPEC.mdis always the spec file - •Sub-features are nested folders
- •Plans live separately in
plans/{pending,current,complete}/ - •Plan filename matches feature name:
auth.md,search.md
INDEX.md Schema
# Spec Index | ID | Feature | Status | Path | Requires | |----|---------|--------|------|----------| | F1 | Auth | in_progress | [auth](auth/SPEC.md) | — | | F1.1 | ↳ OAuth | planned | [auth/oauth](auth/oauth/SPEC.md) | F1 | | F1.2 | ↳ MFA | planned | [auth/mfa](auth/mfa/SPEC.md) | F1 | | F2 | Payments | blocked | [payments](payments/SPEC.md) | F1 | | F3 | Search | complete | [search](search/SPEC.md) | — | ## By Status **In Progress:** F1 **Blocked:** F2 **Planned:** F1.1, F1.2 **Complete:** F3
Status values: planned | in_progress | blocked | complete
SPEC.md Schema
# Feature: [Name] **ID:** F1 **Status:** planned | in_progress | blocked | complete **Requires:** — *(or F2, F3 if dependencies)* ## Summary [2-3 sentences. What is this feature? What problem does it solve?] ## Goals - [What success looks like] - [Key outcome] ## Non-Goals - [Explicit scope boundary] - [What this will NOT do] ## Design ### Overview [How it works conceptually. Architecture decisions. Key flows in prose.] ### Key Files | File | Purpose | |------|---------| | `src/path/to/file.ts` | Brief purpose | ### Data Model [Conceptual description of data structures and storage. Not code.] ### External Dependencies [Services, APIs, infrastructure this feature requires] ## Gotchas [Hard-won learnings. Non-obvious constraints. Things that will bite future devs.] - [Gotcha 1] - [Gotcha 2] ## Sub-Features | ID | Sub-Feature | Status | Path | |----|-------------|--------|------| | F1.1 | Name | status | [path/](path/SPEC.md) | ## Plan **Plan:** [/plans/current/feature-name.md](/plans/current/feature-name.md) ## Open Questions - [ ] Question 1 → *Pending* - [x] Question 2 → **Decision:** Answer ## References - [Link to relevant docs] --- ## Changelog - YYYY-MM-DD: Change description
Working With Specs
Finding a Feature
- •Open
specs/INDEX.md - •Find by name, ID, or status
- •Follow link to
SPEC.md
Creating a New Feature
- •Create folder:
specs/feature-name/ - •Create
SPEC.mdusing schema above - •Add entry to
INDEX.md - •If feature has significant tasks, generate plan using ralph-spec-to-plan skill
Creating a Sub-Feature
- •Create nested folder:
specs/parent/sub-feature/ - •Create
SPEC.mdwithRequires: F[parent] - •Add to parent's Sub-Features table
- •Add to
INDEX.mdwith hierarchical ID (F1.1)
When to Create Sub-Features
Break a feature into sub-features when parts can be logically separated — meaning they could be understood, discussed, or worked on independently.
Good candidates for sub-features:
| Signal | Example |
|---|---|
| Distinct user flows | Auth → Login, Registration, Password Reset |
| Optional/pluggable components | Payments → Stripe, PayPal, Invoice |
| Different integration points | Notifications → Email, Push, SMS |
| Separable concerns | Search → Indexing, Query, Ranking |
| Could be enabled/disabled independently | Auth → MFA, OAuth, SSO |
Keep as one feature when:
- •Parts are tightly coupled and always change together
- •Splitting would create artificial boundaries
- •Sub-parts don't make sense in isolation
- •It's just "big" but conceptually unified
Rule of thumb: If you can explain the sub-feature to someone without first explaining the entire parent, it's a good candidate for separation.
Example structure:
specs/auth/
├── SPEC.md # Core auth: session management, middleware
├── oauth/
│ └── SPEC.md # F1.1: Google, GitHub OAuth providers
├── mfa/
│ └── SPEC.md # F1.2: TOTP, SMS verification
└── password-reset/
└── SPEC.md # F1.3: Reset flow, token management
Updating a Spec
When implementation changes:
- •Update Key Files table if files added/moved/removed
- •Add to Gotchas when you learn something non-obvious
- •Update Status in both
SPEC.mdandINDEX.md - •Add Changelog entry
Do NOT update:
- •Summary, Goals, Non-Goals (these are stable unless feature pivots)
- •Design Overview (unless architecture actually changes)
Completing a Feature
- •Set
Status: completeinSPEC.md - •Update
INDEX.mdstatus - •Ensure Gotchas captures key learnings
- •Ensure Key Files is accurate
- •Add changelog entry
Principles
- •
Specs are maps, not territory. Point to code, don't replicate it.
- •
Gotchas are gold. Capture hard-won learnings immediately.
- •
Key Files = entry points. Link to 3-7 important files, not every file.
- •
Status lives in two places. INDEX.md (for scanning) and SPEC.md (for detail). Keep in sync.
- •
Specs are durable. Written once, updated rarely. If you're updating often, it's implementation detail — put it elsewhere.
- •
No code in specs. Unless it's a gotcha or a critical interface that rarely changes.
Commands
# Find all in-progress features grep "in_progress" specs/INDEX.md # Find feature by ID grep "^| F2 " specs/INDEX.md # List all specs find specs -name "SPEC.md" # Check for specs without INDEX entry for f in $(find specs -name "SPEC.md"); do id=$(grep "^\*\*ID:\*\*" "$f" | sed 's/.*\*\* //') grep -q "$id" specs/INDEX.md || echo "Missing from INDEX: $f" done
Integration With Plans
Specs and plans are separate:
specs/auth/SPEC.md # What and why (durable) plans/current/auth.md # How and status (volatile)
Spec links to plan: **Plan:** [/plans/current/auth.md](/plans/current/auth.md)
Plan lifecycle:
- •Created in
plans/pending/from spec (see ralph-spec-to-plan skill) - •Moved to
plans/current/when work begins - •Moved to
plans/complete/when all tasks done
Anti-Patterns
- •
Code blocks in specs — Rots quickly. Link to files instead.
- •
Detailed API schemas — Put in API docs or code. Spec just describes conceptually.
- •
Updating spec for every code change — Specs are stable. Only update for architectural changes.
- •
Orphaned specs — Always keep INDEX.md in sync.
- •
Specs without Gotchas — If a feature is complete and has no gotchas, you forgot to write them down.