betterspec
Core

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
StateMeaning
proposedSpec files have been scaffolded but work hasn't started
in-progressImplementation is underway; tasks are being checked off
completedAll tasks are done; ready for validation and archival
archivedChange has been archived; knowledge has been extracted

State transitions happen through CLI commands:

  • betterspec propose creates a change in the proposed state
  • Starting work on tasks moves it to in-progress
  • Completing all tasks moves it to completed
  • betterspec archive moves it to archived

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.json

Spec 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 message

specs/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 merged

design.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-side

tasks.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 buttons

Metadata: .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:

FieldDescription
idUnique identifier (matches directory name)
statusCurrent lifecycle state
createdAtWhen the change was proposed
updatedAtWhen 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-oauth

This checks 5 things: proposal exists, requirements exist, scenarios exist, design exists, and tasks exist. All checks should pass before building.

On this page