Skip to main content

Gas Town Architecture

Technical architecture for Gas Town multi-agent workspace management.

Two-Level Beads Architecture

Gas Town uses a two-level beads architecture to separate organizational coordination from project implementation work.

LevelLocationPrefixPurpose
Town~/gt/.beads/hq-*Cross-rig coordination, Mayor mail, agent identity
Rig<rig>/mayor/rig/.beads/project prefixImplementation work, MRs, project issues

Town-Level Beads (~/gt/.beads/)

Organizational chain for cross-rig coordination:

  • Mayor mail and messages
  • Convoy coordination (batch work across rigs)
  • Strategic issues and decisions
  • Town-level agent beads (Mayor, Deacon)
  • Role definition beads (global templates)

Rig-Level Beads (<rig>/mayor/rig/.beads/)

Project chain for implementation work:

  • Bugs, features, tasks for the project
  • Merge requests and code reviews
  • Project-specific molecules
  • Rig-level agent beads (Witness, Refinery, Polecats)

Agent Bead Storage

Agent beads track lifecycle state for each agent. Storage location depends on the agent's scope.

Agent TypeScopeBead LocationBead ID Format
MayorTown~/gt/.beads/hq-mayor
DeaconTown~/gt/.beads/hq-deacon
BootTown~/gt/.beads/hq-boot
DogsTown~/gt/.beads/hq-dog-<name>
WitnessRig<rig>/.beads/<prefix>-<rig>-witness
RefineryRig<rig>/.beads/<prefix>-<rig>-refinery
PolecatsRig<rig>/.beads/<prefix>-<rig>-polecat-<name>
CrewRig<rig>/.beads/<prefix>-<rig>-crew-<name>

Role Beads

Role beads are global templates stored in town beads with hq- prefix:

  • hq-mayor-role - Mayor role definition
  • hq-deacon-role - Deacon role definition
  • hq-boot-role - Boot role definition
  • hq-witness-role - Witness role definition
  • hq-refinery-role - Refinery role definition
  • hq-polecat-role - Polecat role definition
  • hq-crew-role - Crew role definition
  • hq-dog-role - Dog role definition

Each agent bead references its role bead via the role_bead field.

Agent Taxonomy

Town-Level Agents (Cross-Rig)

AgentRolePersistence
MayorGlobal coordinator, handles cross-rig communication and escalationsPersistent
DeaconDaemon beacon — receives heartbeats, runs plugins and monitoringPersistent
BootDeacon watchdog — spawned by daemon for triage decisions when Deacon is downEphemeral
DogsLong-running workers for cross-rig batch workVariable

Rig-Level Agents (Per-Project)

AgentRolePersistence
WitnessMonitors polecat health, handles nudging and cleanupPersistent
RefineryProcesses merge queue, runs verificationPersistent
PolecatsWorkers with persistent identity, assigned to specific issuesPersistent identity, ephemeral sessions
CrewHuman workspaces — full git clones, user-managed lifecyclePersistent

Directory Structure

~/gt/                           Town root
├── .beads/ Town-level beads (hq-* prefix)
│ ├── metadata.json Beads config (dolt_mode, dolt_database)
│ └── routes.jsonl Prefix → rig routing table
├── .dolt-data/ Centralized Dolt data directory
│ ├── hq/ Town beads database (hq-* prefix)
│ ├── gastown/ Gastown rig database (gt-* prefix)
│ ├── beads/ Beads rig database (bd-* prefix)
│ └── <other rigs>/ Per-rig databases
├── daemon/ Daemon runtime state
│ ├── dolt-state.json Dolt server state (pid, port, databases)
│ ├── dolt-server.log Server log
│ └── dolt.pid Server PID file
├── deacon/ Deacon workspace
│ └── dogs/<name>/ Dog worker directories
├── mayor/ Mayor agent home
│ ├── town.json Town configuration
│ ├── rigs.json Rig registry
│ ├── daemon.json Daemon patrol config
│ └── accounts.json Claude Code account management
├── settings/ Town-level settings
│ ├── config.json Town settings (agents, themes)
│ └── escalation.json Escalation routes and contacts
├── config/
│ └── messaging.json Mail lists, queues, channels
└── <rig>/ Project container (NOT a git clone)
├── config.json Rig identity and beads prefix
├── mayor/rig/ Canonical clone (beads live here, NOT an agent)
│ └── .beads/ Rig-level beads (redirected to Dolt)
├── refinery/ Refinery agent home
│ └── rig/ Worktree from mayor/rig
├── witness/ Witness agent home (no clone)
├── crew/ Crew parent
│ └── <name>/ Human workspaces (full clones)
└── polecats/ Polecats parent
└── <name>/<rigname>/ Worker worktrees from mayor/rig

Note: No per-directory CLAUDE.md or AGENTS.md is created. Only ~/gt/CLAUDE.md (town-root identity anchor) exists on disk. Full context is injected by gt prime via SessionStart hook.

Worktree Architecture

Polecats and refinery are git worktrees, not full clones. This enables fast spawning and shared object storage. The worktree base is mayor/rig:

// From polecat/manager.go - worktrees are based on mayor/rig
git worktree add -b polecat/<name>-<timestamp> polecats/<name>

Crew workspaces (crew/<name>/) are full git clones for human developers who need independent repos. Polecat sessions are ephemeral and benefit from worktree efficiency.

Storage Layer: Dolt SQL Server

All beads data is stored in a single Dolt SQL Server process per town. There is no embedded Dolt fallback — if the server is down, bd fails fast with a clear error pointing to gt dolt start.

┌─────────────────────────────────┐
│ Dolt SQL Server (per town) │
│ Port 3307, managed by daemon │
│ Data: ~/gt/.dolt-data/ │
└──────────┬──────────────────────┘
│ MySQL protocol
┌──────┼──────┬──────────┐
│ │ │ │
USE hq USE gastown USE beads ...

Each rig database is a subdirectory under .dolt-data/. The daemon monitors the server on every heartbeat and auto-restarts on crash.

For write concurrency, all agents write directly to main using transaction discipline (BEGIN / DOLT_COMMIT / COMMIT atomically). This eliminates branch proliferation and ensures immediate cross-agent visibility.

See dolt-storage.md for full details.

Beads Routing

The routes.jsonl file maps issue ID prefixes to rig locations (relative to town root):

{"prefix":"hq-","path":"."}
{"prefix":"gt-","path":"gastown/mayor/rig"}
{"prefix":"bd-","path":"beads/mayor/rig"}

Routes point to mayor/rig because that's where the canonical .beads/ lives. This enables transparent cross-rig beads operations:

bd show hq-mayor    # Routes to town beads (~/.gt/.beads)
bd show gt-xyz # Routes to gastown/mayor/rig/.beads

Beads Redirects

Worktrees (polecats, refinery, crew) don't have their own beads databases. Instead, they use a .beads/redirect file that points to the canonical beads location:

polecats/alpha/.beads/redirect → ../../mayor/rig/.beads
refinery/rig/.beads/redirect → ../../mayor/rig/.beads

ResolveBeadsDir() follows redirect chains (max depth 3) with circular detection. This ensures all agents in a rig share a single beads database via the Dolt server.

Merge Queue: Batch-then-Bisect

The refinery processes MRs through a batch-then-bisect merge queue (Bors-style). This is a core capability, not a pluggable strategy.

How It Works

MRs waiting:  [A, B, C, D]

Batch: Rebase A..D as a stack on main

Test tip: Run tests on D (tip of stack)

If PASS: Fast-forward merge all 4 → done
If FAIL: Binary bisect → test B (midpoint)

If B passes: C or D broke it → bisect [C,D]
If B fails: A or B broke it → bisect [A,B]

Implementation Phases

PhaseBeadWhatStatus
1: GatesParallelgt-8b2iRun test + lint concurrently per MRIn progress
2: Batch-then-bisectgt-i2vmBors-style batching with binary bisectBlocked by Phase 1
3: Pre-verificationgt-lu84Polecats run tests before MR submissionBlocked by Phase 2

Gates (test command, lint, etc.) are pluggable. The batching strategy is core.

Design doc: produced by gt-yxx0 review.

Polecat Lifecycle: Self-Managed Completion

Polecats manage their own lifecycle end-to-end. The Witness observes but does NOT gate completion. This prevents the Witness from becoming a bottleneck.

Polecat Completion Flow

Polecat finishes work
→ Push branch to remote
→ Submit MR (bd update --mr-ready)
→ Update bead status
→ Tear down worktree
→ Go idle (available for next assignment)

The Witness monitors for stuck/zombie polecats (no activity for extended period) and nudges or escalates. It does NOT process completion — that's the polecat's job.

Design bead: gt-0wkk.

Data Plane Lifecycle

All beads data flows through a six-stage lifecycle managed by Dogs:

CREATE → LIVE → CLOSE → DECAY → COMPACT → FLATTEN
│ │ │ │ │ │
Dolt active done DELETE REBASE SQUASH
commit work bead rows commits all history
>7-30d together to 1 commit

Stages 1-3 are automated today. Stages 4-6 are being shipped via Dog automation (gt-at0i Reaper DELETE, gt-l8dc Compactor REBASE, gt-emm4 Doctor gc).

See dolt-storage.md for full details.

Deployment Artifacts

Gas Town and Beads are distributed through multiple channels. Tag pushes (v*) trigger GitHub Actions release workflows that build and publish everything.

Gas Town (gt)

ChannelArtifactTrigger
GitHub ReleasesPlatform binaries (darwin/linux/windows, amd64/arm64) + checksumsGoReleaser on tag push
Homebrewbrew install steveyegge/gastown/gt — formula auto-updated on releaseupdate-homebrew job pushes to steveyegge/homebrew-gastown
npmnpx @gastown/gt — wrapper that downloads the correct binaryOIDC trusted publishing (no token)
Local buildgo build -o $(go env GOPATH)/bin/gt ./cmd/gtManual

Beads (bd)

ChannelArtifactTrigger
GitHub ReleasesPlatform binaries + checksumsGoReleaser on tag push
Homebrewbrew install steveyegge/beads/bdupdate-homebrew job
npmnpx @beads/bd — wrapper that downloads the correct binaryOIDC trusted publishing (no token)
PyPIbeads-mcp — MCP server integrationpublish-pypi job with PYPI_API_TOKEN secret
Local buildgo build -o $(go env GOPATH)/bin/bd ./cmd/bdManual

npm Authentication

Both repos use OIDC trusted publishing — no NPM_TOKEN secret needed. Authentication is handled by GitHub's OIDC provider. The workflow needs:

permissions:
id-token: write # Required for npm trusted publishing

Configure on npmjs.com: Package Settings → Trusted Publishers → link to the GitHub repo and release.yml workflow file.

What the binary embeds

The Go binary is the primary distribution vehicle. It embeds:

  • Role templates — Agent priming context, served by gt prime
  • Formula definitions — Workflow molecules, served by bd mol
  • Doctor checks — Health diagnostics, including migration checks
  • Default configsdaemon.json lifecycle defaults, operational thresholds

This means upgrading the binary automatically propagates most fixes. Files that are NOT embedded (and require gt doctor or gt upgrade to update):

  • Town-root CLAUDE.md (created at gt install time)
  • daemon.json patrol entries (created at install, extended by EnsureLifecycleDefaults)
  • Claude Code hooks (.claude/settings.json managed sections)
  • Dolt schema (migrations run on first bd command after upgrade)

See Also