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 PR + review red
  1. Poll — watch 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, Codex, or OpenCode).
  5. Verify — romp re-runs every [verify] command itself. The agent’s own “tests pass” is never trusted.
  6. Push and PR — after verification passes, romp pushes the builder commit and opens the PR. PR creation must succeed before review starts.
  7. Review — code changes go through one concurrent read-only reviewer call per routed lens in the same job slot. Romp merges all lens outcomes into one pass and posts one PR comment. Any failed lens fails the whole pass instead of allowing partial approval. Blocking findings get up to review.max_fix_rounds builder rounds on the same branch. Each round includes fresh verification, push, and a fresh lens fan-out. If verification fails and the budget has another round, the next builder receives the failed command, exit code, and captured output before Romp tries verification again. Re-review receives the prior findings and builder reports, but still sweeps for newly introduced defects. Documentation-only changes skip review but still open a PR.
  8. Complete or recover — approval removes the trigger label. Unresolved review findings become changes-requested. Review failures leave the PR and worktree available with a distinct failure comment.

Components

romp/
├── cmd/romp/          # Cobra commands (init, watch, run, status, ...)
├── internal/
│   ├── config/        # TOML layering, language detection, effort/variant handling
│   ├── harness/       # Claude, Codex, and OpenCode adapters behind a Run/Name interface
│   ├── prompt/        # goal-contract template rendering
│   ├── runner/        # job pipeline: worktree → agent → verify → PR → review
│   ├── 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.

Failed verification output is written to the per-job log. The phase timeline shows the failed command and any transition into another builder round. romp history --review aggregates re-verification failures across the selected history window.

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