Skip to content

Furrow-backed reviewer workspaces: CoW forks per agent instead of one shared checkout #69

Description

@AbirAbbas

Follow-up to #65 (fixed by #68). Suggested by @santoshkumarradha during the incident discussion.

Context

#68 bounds how many agents run at once (shared review-wide semaphore). What it does not change is what they run against: every concurrent reviewer, obligation verifier, and adversary still operates on the same mutable checkout at /workspaces/<repo>-pr<N>, and that shared-workspace design has produced its own bug class:

  • Output/context files are written inside the checkout (.pr-af-context/, harness output files), so concurrent agents can race on them.
  • Workspace reuse across reviews needed a stale-branch fix (fix: review PR head in reused workspace), and clones are never cleaned up (the remaining disk item from OOM on lockfile-regen PRs: Phase 6+6.7 harness fan-out has no shared concurrency budget #65).
  • No agent can safely run anything destructive (tests, builds, codemods) without corrupting the checkout for its 7+ concurrent siblings.

What furrow offers

furrow provides byte-exact, copy-on-write forks of a whole workspace, so agents run in parallel on one machine (or another) with zero merge conflicts. Relevant properties for pr-af:

  1. Per-agent isolation for free — each reviewer/verifier gets a CoW fork of the one materialized checkout. The shared-file race class disappears structurally instead of via careful path conventions.
  2. Shared package state without replication — node_modules / venvs / build caches are forked CoW, not copied N times, so isolation doesn't multiply disk or page-cache footprint the way N clones would.
  3. Destructive commands become safe — a reviewer could actually run the test suite or execute a repro in its fork, which is a capability upgrade for finding real bugs, not just a hygiene fix.
  4. Lifecycle = cleanup — dropping a fork after the agent finishes is the natural place to solve the "workspaces accumulate forever" item left over from OOM on lockfile-regen PRs: Phase 6+6.7 harness fan-out has no shared concurrency budget #65.
  5. Cross-machine potential — forks can move to other machines, which opens the door to spreading a heavy review's agents beyond one container (the same 24 GB box that OOM on lockfile-regen PRs: Phase 6+6.7 harness fan-out has no shared concurrency budget #65 crashed).

Sketch

  • Workspace setup in app.py keeps one canonical checkout per PR (as today).
  • The orchestrator forks it per leaf agent (or per dimension) via the furrow binary and passes the fork path as that agent's repo_path; fork is dropped when the agent returns.
  • af can already install the furrow binary, so the Railway image change should be small; needs verifying in the Docker build.

Open questions

  • Per-fork overhead at pr-af's fan-out width (≤8 concurrent under the new budget) — measure before adopting.
  • Whether opencode's repo scanning benefits from page-cache sharing across forks vs. today's single shared checkout.
  • Fork lifecycle on crash/timeout paths (leaked forks must not recreate the disk-growth problem they're meant to solve).

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions