Files
roboco/docs/rag/architecture/workspaces.md
T

7.5 KiB

Workspace Structure

Multi-Agent Isolation

Each agent gets their own git clone:

{workspaces_root}/
└── {project-slug}/
    └── {team}/
        └── {agent-slug}/
            └── [git repo files]

Example

/data/workspaces/
└── roboco/
    ├── backend/
    │   ├── be-dev-1/    # be-dev-1's workspace
    │   ├── be-dev-2/    # be-dev-2's workspace
    │   ├── be-qa/       # be-qa's workspace
    │   ├── be-pm/       # be-pm's workspace
    │   └── be-doc/      # be-doc's workspace
    ├── frontend/
    │   ├── fe-dev-1/
    │   └── ...
    └── ux_ui/
        └── ...

Configuration

# Environment variables
ROBOCO_WORKSPACES_ROOT=/data/workspaces
ROBOCO_WORKSPACE_AUTO_CLONE=true
ROBOCO_WORKSPACE_CLONE_TIMEOUT=300

Features

Feature Description
Auto-clone Workspaces created on first access
Isolation No file locking conflicts
Branch independence Agents on different branches
Project-scoped Organized by project slug

Benefits

  1. Parallel Development: Multiple agents on same project
  2. No Conflicts: Each has own working tree
  3. Branch Flexibility: Different branches simultaneously
  4. Clean State: Fresh clone if needed

Per-Task Worktrees (F123)

Your agent clone is shared across all your tasks, but each claimed task gets its own linked git worktree — a separate working directory on the same underlying clone — so two of your in-progress tasks never clobber each other on one checkout (this is what lets a coordinator PM hold several roots at once, and what stops a fresh claim from reset --hard-ing uncommitted work on your still-active first task).

{workspaces_root}/{project}/{team}/{agent}/        # the clone root (shared)
├── .git/                  # the real object store (shared)
├── .venv/                 # the per-project venv (shared, agent-owned)
├── .uv-python/            # uv's managed CPython (shared, gitignored)
└── .worktrees/
    └── {task-short}/      # ONE per claimed task — your cwd for that task
        ├── .venv -> ../../.venv   # symlink to the clone-root venv
        └── [your task's checked-out branch]
  • Claim (i_will_work_on / claim_review / claim_doc_task) adds a worktree at .worktrees/{task-id-first-8}/ and checks out the task's branch there. The clone root's HEAD is never moved by a claim.
  • Your container is started with -w pointing at the worktree for your current task, so commit, edits, and uv run all resolve there automatically. Spawn resolves the worktree from your current_task_id on every spawn (never cached), so a resume/respawn re-attaches a pruned worktree before launch. Every spawn also RE-SYNCS an already-present worktree against origin (role-aware): if you're a developer/documenter, your own dirty uncommitted edits are never discarded to do it — a behind-or-equal worktree fast-forwards, a strictly-ahead one (your own unpushed commits) is left exactly alone; if you're QA/PR-gate/PM reviewing someone else's branch, a diverged worktree hard-resets to origin, since your local history there can only ever be a stale prior-round checkout. This closes the "reviewer keeps re-examining its own frozen round-1 checkout across a multi-round bounce" class — you're never respawned onto commits older than what's actually on the branch.
  • The clone-root .venv is shared — each worktree's .venv is a symlink to ../../.venv, so uv run from a worktree resolves the clone-root venv. No per-worktree re-sync.
  • Git ops split by kind: checkout/HEAD-moving ops (create_branch, commit, rebase, checkout) target the worktree; branch-by-name ops (push, pull, fetch, pr_merge, diff) run from the clone root. You never do either by hand — the verbs resolve the worktree for you.
  • One active WorkSession per task is enforced both in the service layer and by a DB unique index — a re-claim (pool release, reaper unclaim, escalation redirect) supersedes any prior agent's stale session for that task.
  • Claim rollback (a mid-claim failure) worktree remove --forces the worktree so a retry doesn't collide with a stale one.
  • Terminal completion (complete / ceo_approve) and cancellation remove the assignee's worktree AND force-delete the now-spent local branch ref in the clone, so finished/cancelled tasks don't leak either on disk. A needs_revision bounce keeps both — you need the branch back. The stale-claim reaper does not remove the worktree or branch; it routes the task to pending for a re-claim that reuses them. A PM/CEO can also run a backlog stale-branch sweep from the panel's Git page for older completed/cancelled tasks whose ref survived from before this reaping existed.

You do not manage any of this. The verbs do. The only thing you must know: your cwd is the worktree for your current task, not the clone root — so relative paths and uv run resolve against your task's checkout.

The /app/.venv is sacred — never retarget onto it

Two venv classes exist in the container:

  • Workspace venvs — per-project, agent-owned, under /data/workspaces/.../{agent}/.venv. These are yours.
  • /app/.venv — the image-baked MCP-gateway venv. The MCP servers (roboco-flow, roboco-do, the git-readonly server) import from here. It is sacred. If it breaks, every tool you have stops spawning.

A past live incident: an agent hit a permission error on its workspace venv, followed uv's hint to run uv run --active, and that retargeted onto VIRTUAL_ENV=/app/.venv (baked globally) — uv rebuilt /app/.venv from a drifted lock and deleted its bin/, bricking every MCP server spawn fleet-wide.

The bash-guard hook now blocks uv run --active and any uv run / uvx against /app (--project /app, --directory /app, UV_PROJECT_ENVIRONMENT=/app, cd /app && uv ...). If you ever feel tempted to use --active or point uv at /app, don't — call i_am_blocked(reason='workspace venv broken') instead and let the environment be rebuilt. Bare uv run (cwd-relative, your workspace venv) is always fine and always what you want.

No Workspace Tools — It's Automatic

There are no agent-facing workspace tools. Workspaces and per-task worktrees are created for you by the orchestrator (WorkspaceService) before your container starts. You never ensure, clone, checkout, or worktree add by hand — your repo is already on disk, the worktree for your current task is already linked and -w'd as your cwd, and the gateway verbs (i_will_work_on, claim_review, ...) check out the right branch in it.

Workspace Resolution

Path resolved automatically: {workspaces_root}/{project}/{team}/{agent}/

If auto_clone=True and workspace doesn't exist, it's created on first access.

Authentication

HTTPS repositories require a git token configured on the project — the field is historically named for GitHub PATs but works unchanged for a project registered against Gitea or GitLab (projects.git_provider):

  • Token configured: Auto-clone works, git operations succeed
  • Token missing: Error "Project requires a git token for HTTPS repositories"

If you see this error: Contact your PM. The project's git token is configured by a human in the control panel (project settings) — it is not an agent tool. The token is encrypted at rest and never exposed to your container; the orchestrator injects it into git operations for you.