Spec File Format
Complete reference for Arial spec files.
Overview
A spec is a markdown file that describes a unit of work for Arial to execute. Each spec file becomes one workstream.
File Location
Specs are stored in a directory you specify:
specs/
├── auth.md → workstream "auth"
├── api.md → workstream "api"
└── tests.md → workstream "tests"The filename (without .md) becomes the workstream ID.
Basic Structure
A spec should include a title and enough context for an AI agent to complete the work:
# Title
## Goal
What you want to achieve.
## Requirements
- Specific requirement 1
- Specific requirement 2
## Technical Notes
- Constraints or preferences
- Libraries to use
- Patterns to followRequired Elements
| Element | Purpose |
|---|---|
| `# Title` | First H1 heading becomes the workstream title |
| Goal/context | Enough information for the agent to understand the task |
Optional Elements
| Element | Purpose |
|---|---|
| `## Goal` | High-level objective |
| `## Requirements` | Specific, verifiable deliverables |
| `## Technical Notes` | Implementation constraints, libraries, patterns |
| `## Context` | Background information, related code |
| `## Examples` | Sample inputs/outputs, API shapes |
Spec Examples
Feature Implementation
# Add User Authentication
## Goal
Implement JWT-based authentication for the API.
## Requirements
- POST /auth/register - Create new user account
- POST /auth/login - Authenticate and return JWT token
- Auth middleware to protect routes
- Password hashing with bcrypt
## Technical Notes
- Use jsonwebtoken package
- Token expiry: 24 hours
- Follow existing error handling patterns in src/middleware/Bug Fix
# Fix Login Rate Limiting
## Goal
Users are being rate limited too aggressively on login attempts.
## Context
Current implementation in src/middleware/rateLimit.ts applies a global limit.
Need per-IP limiting instead.
## Requirements
- Change rate limiter to per-IP tracking
- Allow 5 attempts per minute per IP
- Add proper 429 response with Retry-After header
## Technical Notes
- Use existing Redis connection for state
- Add tests for rate limiting behaviorRefactoring
# Extract Payment Processing Module
## Goal
Payment logic is scattered across multiple files. Consolidate into a single module.
## Files to Refactor
- src/controllers/checkout.ts (lines 45-120)
- src/controllers/subscription.ts (lines 80-150)
- src/utils/stripe.ts (all)
## Requirements
- Create src/modules/payments/
- Move all Stripe interactions to new module
- Maintain existing API contracts
- Update imports across codebase
## Technical Notes
- Keep backward compatibility during transition
- Add index.ts for clean public APIWriting Effective Specs
Be Specific
Vague specs lead to unexpected results:
# Bad: Too vague
Add authentication to the app.
# Good: Specific
Implement JWT-based authentication with:
- Registration endpoint accepting email/password
- Login endpoint returning access token
- Token validation middlewareInclude Context
Reference existing patterns and files:
## Technical Notes
- Follow the controller pattern in src/controllers/users.ts
- Use the existing validation helpers from src/utils/validate.ts
- Match error response format from src/middleware/errorHandler.tsList Verifiable Requirements
Make requirements concrete and testable:
## Requirements
- POST /auth/register returns 201 with user object
- POST /auth/register returns 400 for duplicate email
- POST /auth/login returns 200 with JWT token
- Protected routes return 401 without valid tokenOne Concern Per Spec
Keep specs focused on a single area:
# Good: Focused
specs/
├── auth.md → authentication logic
├── user-api.md → user CRUD endpoints
└── user-tests.md → tests for user features
# Bad: Mixed concerns
specs/
└── users.md → auth + API + tests (too broad)Spec Independence
Since workstreams run in parallel, specs should be independent:
Avoid File Conflicts
If two specs modify the same files, you may get merge conflicts:
# Risky: Both touch src/routes/index.ts
specs/
├── auth-routes.md → adds /auth routes
└── user-routes.md → adds /user routes
# Better: Self-contained
specs/
├── auth.md → adds src/routes/auth.ts
└── users.md → adds src/routes/users.tsAvoid Logical Dependencies
Don't assume one spec completes before another:
# Risky: tests.md depends on auth.md completing first
specs/
├── auth.md → implements auth
└── tests.md → tests auth (but auth might not exist yet)
# Better: Each spec is self-contained
specs/
├── auth.md → implements auth with its own tests
└── api.md → implements API with its own testsWorkstream ID Rules
The workstream ID is derived from the filename:
| Filename | Workstream ID |
|---|---|
| `auth.md` | `auth` |
| `user-api.md` | `user-api` |
| `Add_Feature.md` | `Add_Feature` |
IDs are used in:
- Branch names:
arial/auth-abc123 - Worktree paths:
.arial/worktrees/auth/ - Status output and logs
Title Extraction
The workstream title comes from the first H1 heading:
# Add User Authentication ← This becomes the title
## Goal
...If no H1 is found, the filename is used as the title.