Architecture
autodev is a Rust workspace organized around one rule: policy, storage, execution, orchestration, and presentation should not quietly take responsibility from one another.
Crate boundaries
| Crate | Owns |
|---|---|
autodev-model | Typed entities and pure rules for planning, story workflows, evidence, events, cost, metrics, and retries |
autodev-store | Markdown planning files, git-backed history, repository write locking, and the FleetStore runtime port |
autodev-bridge | Agent harness adapters, process and transcript observation, environment policy, confinement, and mechanical evidence helpers |
autodev-fleet | The reconciler that schedules waves and advances turns, review, integration, gates, apply, retries, and recovery |
autodev-workflow | The coordinator workflow language as Rust structs: the verb catalog, typed nodes with a closed kind enum per domain, DAG validation, the builder the built-ins are written with, and the YAML encoding |
autodev-canvas | The declarative canvas vocabulary, schema validation, datasource bindings, resolution, and encoding |
autodev-cli | Command parsing, human/JSON rendering, the central daemon, and the loopback operator workspace for board, fleet, conversation, workspace, daemon, and the read surfaces |
The CLI is deliberately thin: model decisions belong in the model crate, filesystem facts in the store, harness behavior in bridges, and lifecycle orchestration in the fleet.
Two durable surfaces
Planning store
Planning is repository content. The loader reads the working tree so an uncommitted edit is still a real edit rather than an invisible one.
docs/stories/ story contracts
docs/epics/ epic contracts
docs/designs/ referenced designs
docs/decisions/ architectural decisions
docs/glossary/ shared terminology
Files use Markdown bodies and typed frontmatter. A malformed or unrepresentable file becomes a load issue; the loader does not silently drop it and pretend the entity is absent. Git history supplies planning lifetime data without a second mutable counter.
Fleet store
Runtime state lives behind the FleetStore trait. An unregistered repository may use its local
.autodev/fleet.sqlite backend in process. A registered workspace instead reaches the daemon's one
global ~/.local/share/autodev/fleet.sqlite over HTTP; if the daemon is unavailable, the store is
unreachable rather than replaced with a local history. The memory, local SQLite, and HTTP
implementations run the same executable store contract.
Waves and workers are typed, individually revisioned records; updates use compare-and-set so a stale writer receives a conflict instead of overwriting newer state. Workspace-scoped records inside the daemon-owned database are enforced by the executable store contract.
Handoffs and deliveries are append-only facts. Events have a strict sequence, timestamp, and actor. Transcripts are stored once by reference and bounded by an explicit budget.
Control projection
The daemon's client surface projects the two durable surfaces into the embedded operator workspace. Its opening snapshot includes board entities and whole-store delivery facts; its websocket continues from the store event sequence. Browser filters, layout preferences, open drawers, and time-travel cursors are view state only.
Canvas documents are validated declarations over a closed widget vocabulary. Datasource handles are resolved by the host under the current principal's grants; declarations cannot carry scripts or credentials.
Execution boundary
AgentBridge is the port between autodev and an agent harness. Built-in adapters support Codex,
Claude Code, and an operator-provided command template. A bridge is responsible for launching one
turn, streaming output, observing the process and git result, and reporting usage honestly.
Bridges do not decide that work is acceptable. The host independently builds evidence and the fleet owns the transition to review, integration, and delivery. Repository configuration binds named bridges to roles, so planning data never needs a vendor-specific model identifier.
Concurrency and serialization
The expensive read/write-isolated work overlaps where its artifacts do not share a mutable target: worker turns use separate worktrees, and review turns use separate read-focused checkouts. Capacity is configured independently from how many stories a wave batches.
Integration and base-ref advancement are serial by design:
- each integration must start from the current accepted tip and gate the tree it creates;
- each apply advances the shared base ref only after the post-merge result has passed its gate.
Parallelizing either operation would let two green decisions be made against trees that omit one another.
Process topology
browser
│ HTTP + websocket, loopback :7777
▼
daemon client + drive ───────┐
│ dyn FleetStore
CLI ─────────────────────────┤
├── unregistered repository → local .autodev/fleet.sqlite
│
└── registered workspace → HTTP/JSON :7788 → daemon → global fleet.sqlite
The daemon owns runtime state and registered-workspace drives. The browser client and machine API
are listeners in that same process but remain on separate sockets. serve retains a temporary
standalone compatibility path; it is not the normal topology. A board read in an unregistered
repository remains available with no daemon running.
Configuration surfaces
| Path | Purpose |
|---|---|
.autodev/fleet.toml | Bridges, role bindings, validation and gate commands, environment policy, capacity, retry, resource, and transcript limits |
.autodev/workflows.toml | Optional repository story-workflow definitions that shadow matching built-ins |
.autodev/coordinator.yaml | Optional repository coordinator workflow graphs, applied over the built-in; inspect the result with autodev workflow show |
.autodev/fleet.sqlite | Runtime state for an unregistered repository, or legacy history awaiting import after registration |
~/.local/share/autodev/fleet.sqlite | One daemon-owned runtime store, globally shared and workspace-scoped |
| Platform data directory | Central workspace registry, endpoint record, token material, and the global daemon store |
The architecture keeps the core model portable while the repository decides how to run it. The trust and evidence boundary stays in the host around every configured harness.