Spec Workflow
How to create and manage specification documents in the swarm project.
Overview
Swarm uses a spec-first development process. Before implementing a feature or making significant changes, you write specification documents that capture the design, contracts, and invariants. These specs serve as the authoritative source of truth for implementation and are stored in specs/.
Why Specs First?
- Clarity — Forces you to think through the design before writing code
- Reviewability — Easier to review a design document than a large code PR
- Agent-friendly — AI agents can read specs to understand what to implement
- Traceability — Each implementation task links back to its spec
Spec Categories
The specs/ directory contains three categories of documents:
Architecture Decision Records (ADRs)
ADRs document significant architectural choices with rationale. They live in docs/src/adr/ and are numbered sequentially:
docs/src/adr/
001-tokio-async.md
002-sqlite-messaging.md
003-agent-backend-trait.md
...
Write an ADR when you need to:
- Choose between competing approaches (e.g., SQLite vs Redis for messaging)
- Make a decision that affects the whole system (e.g., async runtime choice)
- Document why something was done a certain way for future contributors
Contract Documents
Contracts define the precise interface and behavior of a module or subsystem. They're the most common spec type:
specs/
contract-config-schema.md
contract-agent-state-machine.md
contract-mailbox-schema.md
...
A contract includes:
- File location (which source files implement it)
- Type definitions (structs, enums, traits)
- Method signatures and behavior
- Invariants and validation rules
- Error handling
Plan Documents
Plans describe a multi-step implementation strategy. They're used for larger efforts that span multiple sessions:
specs/
plan-sdk-integration.md
plan-mailbox-migration.md
Writing a Spec
Step 1: Choose the Right Type
| Situation | Spec Type |
|---|---|
| Choosing between approaches | ADR |
| Defining a module's interface | Contract |
| Planning a multi-session effort | Plan |
Step 2: Create the File
Use a descriptive name with the appropriate prefix:
# Contract
touch specs/contract-my-feature.md
# ADR (in docs)
touch docs/src/adr/011-my-decision.md
Step 3: Write the Content
Contract Template
# Contract: [Feature Name]
## File Location
`swarm/src/my_module.rs`
## Overview
Brief description of what this module does and why it exists.
## Type Definitions
```rust
pub struct MyStruct {
pub field: Type,
}
pub enum MyEnum {
Variant1,
Variant2 { data: String },
}
Methods
| Method | Signature | Description |
|---|---|---|
new() | fn new() -> Self | Create instance |
process() | async fn process(&self, input: Value) -> Result<Output> | Process input |
Invariants
- [Rule that must always hold]
- [Another rule]
Error Handling
| Error | When | Recovery |
|---|---|---|
MyError::NotFound | Item doesn't exist | Return error to caller |
Related
- [Link to related spec or ADR]
#### ADR Template
```markdown
# ADR-NNN: [Title]
## Status
Accepted | Proposed | Superseded by ADR-XXX
## Context
What problem are we solving? What constraints exist?
## Decision
What did we decide?
## Consequences
### Positive
- Benefit 1
- Benefit 2
### Negative
- Tradeoff 1
### Neutral
- Observation
Step 4: File Tasks from the Spec
After writing the spec, create beads tasks that reference it:
bd create "Implement MyStruct per specs/contract-my-feature.md"
bd create "Add tests for MyStruct per specs/contract-my-feature.md"
bd create "Add MyStruct to registry per specs/contract-my-feature.md"
Break large specs into small, independently implementable tasks. Each task should:
- Reference the spec file
- Describe a specific deliverable
- Be completable in a single session
The Full Workflow
1. Identify need → "We need feature X"
2. Write spec → specs/contract-feature-x.md
3. Review spec → Get feedback, iterate
4. File tasks → bd create "Implement X per specs/..."
5. Implement → Pick up tasks with bd ready
6. Verify → Check implementation against spec
7. Update spec → If the implementation diverged, update the spec
Spec Conventions
Do
- Be precise about types — Use real Rust type signatures, not pseudocode
- Include invariants — Document rules that must always hold
- List error cases — Every error variant with when it occurs
- Link related specs — Cross-reference ADRs and other contracts
- Keep specs updated — When implementation changes, update the spec
Don't
- Don't write implementation code — Specs describe what, not how
- Don't duplicate — Reference other specs instead of copying
- Don't over-specify — Leave implementation details to the implementer
- Don't write stale specs — Archive or update specs that no longer apply
Existing Specs
The specs/ directory currently contains 59 documents:
- 10 ADRs — Major architectural decisions
- ~46 contracts — Module interfaces and behavior
- 3 plans — Multi-session implementation strategies
Use ls specs/ to see all spec files, or check specs/README.md for an index.
Related
- Development — Development setup and workflow
- Beads Workflow — Task tracking with beads
- Architecture — System architecture overview