Part 08 of 13

Running 4 Agents at Once

Queue-based self-scheduling across machines. Database branching for isolation. Trunk-based development with rebase. Conflict resolution patterns.

~8 minute read

Why Parallelism Matters

A solo founder with 150+ units cannot build them sequentially. At 4-5 hours per spec, sequential execution means 600-750 hours of agent time for the first version. With 4 parallel instances, that compresses to 150-190 hours of wall clock time.

But parallel execution introduces coordination problems: merge conflicts, database schema collisions, resource contention, and scheduling dependencies. This section covers how to solve each one.

Queue-Based Self-Scheduling

A shared JSON file (agents/queue.json) tracks all specs across three arrays: ready (waiting for execution), in_progress (being worked on), and completed (pushed to main). When a command runs without arguments, it reads the queue and recommends the next spec.

The Scheduling Algorithm

  1. Filter by dependencies. Only specs whose dependencies are all in "completed" are eligible.
  2. Exclude conflicts. Skip specs whose files_modified destructively overlap with any in-progress spec. Additive overlap (both add new files) is fine. Destructive overlap (both modify the same existing file) requires sequential execution.
  3. Apply priority. Dependency unblocking (specs that unblock others first) > critical path > conflict avoidance > FIFO.
  4. Recommend. Present the top candidate with rationale. Human confirms.

Status progression: ready > testing > tests-written > implementing > implemented > verifying > complete

One spec, one machine, end-to-end. All three commands (ex-test, ex-impl, ex-verify) for a given spec execute on the same machine. The spec never moves between machines. This eliminates cross-machine state synchronization.

Database Branching for Isolation

Each spec creates three separate database branches (one per command), each from the current dev branch. Branches are created in ~1 second using copy-on-write (no physical data copy) and cost fractions of a cent per hour.

Why Three Branches Instead of One

The Migration Strategy

During execution, schema changes use push (applies the schema diff directly to the branch, no migration files). This avoids migration file conflicts when multiple specs execute in parallel.

Canonical migration files are generated only by ex-verify, as the final step before pushing to main. If two specs merged between creation and push, the migration number may conflict. Resolution: delete local migration files, regenerate from the current schema state, retest.

Git on Main: Trunk-Based Development

No feature branches. No pull requests. All work on main. Rebase before start and before push.

This extreme trunk-based approach works because:

Conflict Resolution Table

Conflict TypeResolutionAutomated?
Both add new files in same directoryNo conflict. Both coexist.Yes
Both modify root router (add registration)Additive. Rebase auto-resolves.Yes
Lock file (pnpm-lock.yaml)Accept theirs, re-run install, re-add.Yes
Same migration numberDelete local, regenerate, retest.Yes
Same file, same linesSTOP. Report to human.No
Turbo daemon lock file. If using Turborepo, the turbo daemon can create .git/index.lock during rebases, blocking the operation. Always run turbo daemon stop before any rebase. This is built into every command's rebase step.

Resource Management

Machine Configuration

Each machine has a .machine file (gitignored) that the scheduling algorithm reads. It contains: machine name, type, RAM, concurrent instance count, and Playwright worker limits.

A setup script auto-detects hardware and calculates optimal Playwright worker counts based on available memory after accounting for the AI agent's memory usage (~6GB per instance).

E2E Test Framework Memory

Research note [R5]: Playwright 1.57+ switched from open-source Chromium to Chrome for Testing, causing 20GB+ memory consumption with 3 workers on macOS (GitHub #38489). System load exceeds 27 on a 16GB M1 Mac. Pin Playwright below 1.57 until resolved. See Research: R5.

Context Window Management

All commands run a proactive compaction at 60% context capacity. Do not wait for auto-compact at 95%. When compacting, preserve: current task, which tests pass/fail, files modified, decisions made, spec ID.

The spec header includes a context budget estimate. If the budget was underestimated and context reaches 60% during execution, the command compacts proactively rather than risking quality degradation.