Architecture

How romp works under the hood.

romp is a Go CLI that drives your local coding agent. It is deliberately minimal: the durable source of truth is GitHub, and romp adds only the machinery to claim, isolate, and verify work.

Job lifecycle

self-reject pass fail Label issue Poll Claim Worktree Agent Verify blocked Open PR red
  1. Pollwatch lists open issues carrying the trigger label every 60 seconds. The label is the entire queue; there is no local backlog.
  2. Claim — atomic insert (unique on repo + issue), claim label, assign @me. Concurrent watchers on other machines skip claimed issues.
  3. Worktree — each job runs in a fresh git worktree branched from the default branch. Never the local tree; the base is deterministic.
  4. Agent — the goal contract is rendered and handed to the harness (claude or codex).
  5. Verify — romp re-runs every [verify] command itself. The agent’s own “tests pass” is never trusted.
  6. PR or block — green and scoped means a PR and label removal; an under-scoped issue becomes blocked with a gap comment.

Components

romp/
├── cmd/romp/          # Cobra commands (init, watch, run, status, ...)
├── internal/
│   ├── config/        # TOML layering, language detection, effort validation
│   ├── harness/       # claude + codex adapters behind a Run/Name interface
│   ├── prompt/        # goal-contract template rendering
│   ├── runner/        # job pipeline: worktree → agent → verify → PR/block
│   ├── watch/         # poll loop + claim + cancel socket
│   ├── job/           # SQLite job table + outcome history
│   ├── gh/            # GitHub client with rate-limit retry
│   ├── git/           # worktree and branch management
│   └── codename/      # deterministic adjective_name per job
└── docs/adr/          # design decisions

Isolation and concurrency

  • Worktree isolation — concurrent jobs never share a checkout.
  • Width — an in-memory semaphore bounds concurrent jobs per repo.
  • Cross-machine dedupe — the claim label, not any local state, is the authority across machines.
  • Crash recovery — a fresh watcher clears only its own stale in-flight rows and reconciles issues whose romp-N branch already has an open PR.

Observability

Every job gets a codename — an adjective_name pair like sunny_naruto, derived deterministically from the repo and issue number. The codename prefixes every log line, names the per-job log file, and is the primary column in status.

State lives in one SQLite file per machine: ~/.local/state/romp/romp.db. The jobs table holds exactly the in-flight set; finished jobs move to the append-only outcomes table in one transaction.

Design decisions (ADRs)

# Decision Status
0001 An explicit verify command, independently re-run accepted
0002 Prompt contract; outcomes via .romp/ files accepted
0003 GitHub is the source of truth; ephemeral worktrees accepted
0004 TOML layered with a zero-means-default overlay accepted
0005 Atomic claim, configurable claim label, in-flight job table accepted
0006 Job codenames, status, per-job logs, and gc accepted
0007 Poll the trigger label in v0; webhooks deferred accepted
0008 Shared SQLite file and append-only outcome history accepted
0009 Cancel over a Unix socket; logs tail files superseded by 0010
0010 One machine-wide daemon, one socket, HTTP clients accepted