Specs & Changes
The lifecycle and structure of betterspec change specifications.
Specs & Changes
A change is the fundamental unit of work in betterspec. Every feature, refactor, or fix is tracked as a change with a full set of specification files. These specs give AI agents (and humans) the context they need to plan, build, validate, and archive work correctly.
Change Lifecycle
Every change moves through four states:
proposed → in-progress → completed → archived| State | Meaning |
|---|---|
proposed | Spec files have been scaffolded but work hasn't started |
in-progress | Implementation is underway; tasks are being checked off |
completed | All tasks are done; ready for validation and archival |
archived | Change has been archived; knowledge has been extracted |
State transitions happen through CLI commands:
betterspec proposecreates a change in theproposedstate- Starting work on tasks moves it to
in-progress - Completing all tasks moves it to
completed betterspec archivemoves it toarchived
Directory Structure
Each change lives in its own directory under betterspec/changes/:
betterspec/changes/auth-oauth/
proposal.md
specs/
requirements.md
scenarios.md
design.md
tasks.md
.betterspec-meta.jsonSpec Files
proposal.md
The starting point for every change. Describes what you want to change and why. This is written in natural language and should capture the motivation, context, and high-level goal.
# Add OAuth Authentication
## What
Add OAuth 2.0 authentication using GitHub and Google providers.
## Why
Users currently rely on password-based auth, which has higher friction
and lower security than OAuth.specs/requirements.md
Defines what must be true when the change is complete. Requirements are concrete, verifiable statements — not implementation details. Think of these as acceptance criteria.
# Requirements
- Users can sign in with GitHub OAuth
- Users can sign in with Google OAuth
- Existing password-based accounts can link OAuth providers
- Sessions expire after 24 hours of inactivity
- Failed OAuth attempts show a user-friendly error messagespecs/scenarios.md
Describes how the system should behave through concrete scenarios. These cover happy paths, edge cases, and error conditions. Scenarios are the basis for validation.
# Scenarios
## Happy Path: GitHub Sign-In
1. User clicks "Sign in with GitHub"
2. User is redirected to GitHub authorization page
3. User approves access
4. User is redirected back and signed in
5. Session token is set in cookies
## Edge Case: Existing Email
1. User signs in with Google using an email that already has a password account
2. System prompts user to link accounts
3. User confirms and accounts are mergeddesign.md
Describes how the change will be built. Covers architecture, key decisions, dependencies, and trade-offs. This is where technical details live.
# Design
## Approach
Use the `arctic` library for OAuth provider handling.
Add a `oauth_accounts` table linked to the existing `users` table.
## Key Decisions
- Store OAuth tokens encrypted at rest
- Use PKCE flow for all providers
- Handle token refresh server-sidetasks.md
The implementation plan broken into ordered, checkable steps. Each task should be small enough to complete in a single focused session. betterspec parses the checkboxes to track progress.
# Tasks
- [ ] Install arctic and configure OAuth providers
- [ ] Create oauth_accounts database migration
- [ ] Implement GitHub OAuth callback handler
- [ ] Implement Google OAuth callback handler
- [ ] Add account linking flow for existing users
- [ ] Add session expiry logic
- [ ] Write integration tests for OAuth flows
- [ ] Update login UI with OAuth buttonsMetadata: .betterspec-meta.json
Each change directory contains a .betterspec-meta.json file that tracks machine-readable metadata. This file is managed by betterspec — you typically don't edit it by hand.
{
"id": "auth-oauth",
"status": "in-progress",
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-01-16T14:22:00Z"
}Fields include:
| Field | Description |
|---|---|
id | Unique identifier (matches directory name) |
status | Current lifecycle state |
createdAt | When the change was proposed |
updatedAt | When the metadata was last modified |
Verifying a Change
Before starting implementation, run betterspec verify to check that all spec files are present and well-formed:
betterspec verify auth-oauthThis checks 5 things: proposal exists, requirements exist, scenarios exist, design exists, and tasks exist. All checks should pass before building.