agent-orchestrator/docs/stack.md

5.7 KiB

AO technical stack

This is the source of truth for library and runtime choices in the AO rewrite.
Keep this document about durable technology decisions; use status.md for
implementation progress and architecture.md for component behavior and
invariants.

Principles

  • Prefer the Go standard library until a small dependency clearly earns its
    place.
  • Keep the backend daemon boring: explicit process control, explicit SQL,
    narrow adapters, and observable failure modes.
  • Shell out where AO needs the user's real developer-machine behavior, especially
    for Git and terminal multiplexers.
  • Keep high-volume terminal output out of SQLite; store structured state in the
    database and stream/log payload-heavy data separately.

Accepted stack

Area Decision Status Rationale
Backend language Go 1.25.7 Implemented Matches backend/go.mod; small daemon, strong stdlib, easy local distribution.
Backend core Go stdlib Implemented Domain, lifecycle, session, and adapter contracts should stay dependency-light.
Frontend shell Electron + TypeScript Implemented Local desktop control plane paired with the daemon.
Runtime adapter zellij CLI via os/exec Implemented Terminal multiplexing fits long-running sessions, attach/debug workflows, and adapter isolation.
Terminal PTY github.com/creack/pty Implemented PTY-backed terminal sessions with resize/input/output control.
Git/worktrees git CLI via os/exec Implemented Uses real repo behavior, credentials, hooks, LFS, submodules, and user config.
HTTP API net/http + github.com/go-chi/chi/v5 Implemented Lightweight, idiomatic router without committing AO to a large web framework.
WebSocket github.com/coder/websocket Implemented Small WebSocket library for terminal streaming.
Storage SQLite in WAL mode via database/sql Implemented Local daemon, single writer, many dashboard/API reads, no external DB setup.
SQLite driver modernc.org/sqlite Implemented Current pure-Go driver in backend/internal/storage/sqlite; keep it swappable behind database/sql.
SQL generation github.com/sqlc-dev/sqlc Implemented Hand-written SQL with generated typed methods from backend/sqlc.yaml.
Migrations github.com/pressly/goose/v3 Implemented Simple SQL migrations for the embedded/local database.
CLI github.com/spf13/cobra Implemented Standard command structure for daemon startup, diagnostics, and admin commands.
Config stdlib environment loading + SQLite-backed state/config Implemented / evolving internal/config handles daemon env/defaults; durable product config belongs in SQLite, so no config framework is selected for V1.
Logging log/slog Implemented Stdlib structured logging before adding another logging dependency.
OpenAPI generation github.com/swaggest/openapi-go, github.com/swaggest/jsonschema-go, gopkg.in/yaml.v3 Implemented Generated OpenAPI keeps route contracts close to Go DTOs.
Testing stdlib testing Implemented Keep pure domain logic and adapter contracts easy to test.
Test assertions github.com/stretchr/testify/require Planned if needed Concise assertions for higher-level adapter and integration tests; do not add unless tests benefit.
Packaging github.com/goreleaser/goreleaser Planned Cross-platform release automation, checksums, and future Homebrew support.

Pending decisions

SQLite driver validation

Current main uses modernc.org/sqlite. Before release packaging is locked,
validate github.com/ncruces/go-sqlite3/driver against AO's WAL, migration,
and change_log/CDC workload. It is the preferred no-CGO candidate if it passes
compatibility and performance checks.

Keep the driver behind database/sql so the persistence layer can switch
drivers without changing store interfaces.

Required SQLite setup:

PRAGMA journal_mode = WAL;
PRAGMA busy_timeout = 5000;
PRAGMA foreign_keys = ON;
PRAGMA synchronous = NORMAL;

Config model

Current daemon config is stdlib env/default loading. Project and product config
should be persisted in SQLite when it needs durability or user editing. Do not
add github.com/spf13/viper or github.com/knadh/koanf unless a real file-based
config surface appears.

Explicitly avoided for V1

Avoid Reason
GORM AO needs explicit transactional SQL and CDC-triggered writes.
Gin/Fiber net/http + chi is enough for a local daemon API.
go-git as the primary Git engine AO should match installed Git behavior, credentials, hooks, LFS, submodules, and user config.
github.com/spf13/viper / github.com/knadh/koanf by default Env/default loading plus SQLite-backed config is enough for V1.
Temporal / NATS / Kafka / Redis V1 is a local daemon with SQLite and CDC, not a distributed control plane.
Full plugin framework Keep adapter interfaces narrow until product needs justify a plugin runtime.
Multi-sink CDC fan-out Start with one durable local delivery path; add fan-out later if needed.

Current stack mapping

Go daemon
  net/http + github.com/go-chi/chi/v5
  github.com/coder/websocket
  github.com/creack/pty
  zellij runtime adapter via os/exec
  git worktree adapter via git CLI
  SQLite via database/sql + modernc.org/sqlite
  github.com/sqlc-dev/sqlc generated queries
  github.com/pressly/goose/v3 migrations
  log/slog
  github.com/spf13/cobra CLI
  SQLite change_log + CDC poller

This stack supports the current architecture: durable session/PR/project facts,
derived display status, SQLite change_log CDC, terminal sessions, and real Git
worktrees.