Openspec workflow

How changes are proposed, designed, spec'd, implemented, and archived in this repo.

Openspec is the spec-driven change workflow this repo uses for anything non-trivial. Every meaningful change — new feature, refactor, migration, docs overhaul — passes through a small set of artifacts that capture why, how, what, and in what order before a single line of implementation lands.

The point isn't ceremony. It's that a proposal forces you to think about surfaces before you touch them, a design forces you to commit to an approach before you type, and a phased tasks file lets multiple agents run in parallel worktrees without colliding.

Source of truth

Workflow configuration lives at openspec/config.yaml. That file defines the schema (spec-driven), the project context injected into every artifact, and the per-artifact rules (proposal, tasks) that the openspec CLI enforces. If this page drifts, trust openspec/config.yaml.

The artifacts

A change lives at openspec/changes/<name>/ and is a directory of markdown files. Each file has a distinct job:

ArtifactAnswersRequired before
proposal.mdWhat are we doing, and why? Which surfaces does it touch?design
design.mdHow will we do it? What are the tradeoffs and alternatives?specs, tasks
specs/<capability>/spec.mdWhat does the new or changed behavior look like as a capability spec?archive (synced to main)
tasks.mdWhat concrete work, in what order, by which teams?apply / implementation
.openspec.yamlMetadata: schema, status, which artifacts are done.always present (auto-managed)

Proposals are deliberately short — they capture scope and why, not how. Architecture, tradeoffs, and implementation strategy belong in design.md. The split exists so a reviewer can evaluate whether a change should happen without having to read the full engineering plan.

The lifecycle

1

Propose

Create the change directory with openspec new change "<name>", then fill in proposal.md (including a ## Surfaces affected section), design.md, specs/, and tasks.md. The opsx:propose skill does all of this in one go.

2

Apply

Implement the tasks. The opsx:apply skill reads tasks.md, detects whether it's phased or flat, and either dispatches parallel team agents in worktrees or walks tasks sequentially. Task checkboxes are flipped from - [ ] to - [x] as work lands.

3

Archive

When all tasks are done, opsx:archive moves the change to openspec/changes/archive/YYYY-MM-DD-<name>/, syncs any delta specs to the main spec tree at openspec/specs/, and verifies that declared surfaces actually match the diff.

The spec tree at openspec/specs/ is the living record of what the system does. The archive at openspec/changes/archive/ is the historical record of what the system did, one change at a time. You read the former to understand the current system and the latter to understand how it got there.

The skills

Five skills wrap the workflow. Invoke them with slash commands in Claude and Cursor, or call the underlying openspec CLI directly in Codex.

CommandPurposeWhen to use
opsx:proposeCreate a new change with all artifacts generated in one step.You have a change in mind and want to scope it before implementation.
opsx:applyImplement the tasks from an existing change.Artifacts are in place and you're ready to code. Supports parallel dispatch across phased teams.
opsx:exploreThinking-partner mode. Read, investigate, diagram — never implement.You're not sure yet what the change should be, or you're stuck mid-implementation.
opsx:archiveFinalize a completed change, sync specs, move to archive/.All tasks are done and you want to retire the change.
opsx:continueResume a partially complete change.You stopped mid-apply and want to pick up where the last session left off.

When to use opsx:propose vs editing specs directly

Use opsx:propose when you're making a change — adding a capability, modifying behavior, migrating something, deprecating an API. Anything that a reader a year from now should be able to trace back through an archived change record.

Edit openspec/specs/ directly only for pure corrections: typos, stale paths, renamed files, broken cross-links. If the edit documents a decision or a new behavior, it belongs in a change proposal.

The rule of thumb: if you'd want a git archaeologist to find a proposal and a design.md explaining why, write a change proposal. If the edit is trivially obvious from context, edit the spec.

The phased execution plan

tasks.md is the workhorse of the whole system. It organises work into numbered phases, splits each phase into parallel teams, and tags every team with a model hint and (optionally) a worktree marker so opsx:apply knows which teams can run concurrently in isolated git worktrees.

The format is load-bearing — the opsx:apply skill parses it to drive parallel dispatch. Every non-trivial change ends with an execution summary table so the plan is legible at a glance.

markdown
## Phase 1 — Component Implementation (parallel worktrees)
 
> **5 agent teams** running in parallel worktrees. Each team owns a distinct set
> of files — no overlap. Barrel exports are consolidated in the merge step.
 
### Team A: Core + Code Components `sonnet` `worktree`
 
- [ ] A.1 Implement `Callout` component with tip/info/warning/danger variants
- [ ] A.2 Implement `Tabs` / `TabItem` wrapper around shadcn/ui Tabs
- [ ] A.3 Implement `LinkCard` and `LinkCardGrid` with responsive grid
- [ ] A.4 Implement `CodeBlock` component with Shiki syntax highlighting
 
### Team B: Design Token Components `sonnet` `worktree`
 
- [ ] B.1 Implement `ColorPalette` component reading CSS custom properties
- [ ] B.2 Add "semantic" mode showing shadcn/ui semantic tokens
- [ ] B.3 Implement `SpacingScale` with horizontal bars and rem/px values
 
### Phase 1 Merge
 
- [ ] M.1 Merge all worktree branches into main, resolve conflicts in `src/index.ts`
- [ ] M.2 Consolidate barrel exports into `packages/docs-ui/src/index.ts`
- [ ] M.3 Verify `pnpm build` succeeds for the packages touched this phase
 
## Execution Summary
 
| Phase | Teams | Model | Parallelism | Est. Tasks |
|-------|-------|-------|-------------|------------|
| 0 — Foundation | 1 agent | haiku | sequential | 10 |
| 1 — Components | A `sonnet` · B `sonnet` | 2 worktrees | 7 |
| 1 — Merge | 1 agent | sonnet | sequential | 3 |
31 lines of markdown code

A few things to notice:

  • Phase headers are H2 markdown (## Phase N — name). They always run sequentially — the current phase waits for the previous merge to finish.
  • Team headers are H3 markdown (### Team A: Core followed by inline-code tags for the model hint and an optional worktree marker). The model hint is one of haiku, sonnet, or opus.
  • Task identifiers prefix with the team letter (A.1, B.3) or the phase number for phase-level tasks (0.1). Merge tasks use M.x.
  • Every parallel phase ends with a merge section (### Phase N Merge) that consolidates barrel exports, configs, and build verification. The merge is never skipped.
  • Execution summary is a markdown table at the bottom with columns | Phase | Teams | Model | Parallelism | Est. Tasks |.

The canonical reference for this format is openspec/changes/archive/2026-04-03-docs-site-and-docs-ui/tasks.md — the change that built this very documentation site.

Model hints

The model hint on each team is a budget signal for the dispatcher:

HintUse for
haikuBoilerplate, config, repetitive edits, scaffolding.
sonnetStandard component or feature implementation.
opusComplex architecture decisions, integration work, tricky refactors.

If your tool supports runtime model switching, it uses the hint directly. If not, treat the hint as informational — the tasks are still correct, you just pay for the more capable model everywhere.

Surfaces affected

Every proposal must declare which surfaces it touches in a ## Surfaces affected section, drawn from .ai/surfaces.yaml. This is the main guardrail against forgetting a moving part during proposal time. The Surfaces inventory page documents how the list is maintained and how proposals verify coverage at archive time.

What's next?

  • Read the Skills registry to see how the five openspec skills are wired into Claude, Codex, and Cursor.
  • Browse openspec/changes/archive/ for end-to-end examples of real changes.
  • Run openspec list --json to see what's currently active in your checkout.