Skip to content

feat: worktree-based isolation for concurrent agent runs #5

@sixty4bit

Description

@sixty4bit

Problem

Running multiple agents simultaneously causes conflicts across several shared resources. There's no isolation between concurrent runs, so two agents targeting the same repo (or even different repos) can corrupt each other's state.

Shared mutable state risks

Resource Location Risk
task.json files tasks/active/ Two agents writing the same .task.json simultaneously → last write wins, data loss
.case/active marker Target repo root Multiple agents in the same repo overwrite each other's active task marker
Task state transitions task-status.sh Read-then-write with no atomic CAS — race between checking current status and writing new status
Task ID generation Counts existing .md files Two agents creating tasks simultaneously get the same sequential ID
Git branches Target repos Two agents calling git checkout -b on the same repo can collide

Hardcoded paths

/Users/nicknisi/Developer/case is hardcoded in ~100+ locations across:

  • skills/case/SKILL.md (~50 references)
  • skills/from-ideation/SKILL.md (~20 references)
  • agents/*.md (implementer, verifier, closer, retrospective)
  • scripts/mark-*.sh (CASE_REPO variable)
  • AGENTS.md
  • docs/playbooks/implement-from-spec.md
  • docs/ideation/ specs

The TypeScript orchestrator (src/) already resolves paths dynamically via CASE_ROOT, but the SKILL.md and agent prompt files are stale and still reference the hardcoded path. Anyone running from a different location (or in a worktree) will hit broken paths.

Proposal

Make agent runs worktree-isolated by default so multiple bots can operate concurrently without interference.

1. Git worktree per agent run

Each agent run should create a temporary git worktree for the target repo. This gives each agent an isolated working directory with its own branch, index, and working tree — no branch collisions, no uncommitted changes bleeding between runs.

2. Dynamic path resolution everywhere

Replace all hardcoded /Users/nicknisi/Developer/case references with dynamic resolution:

  • SKILL.md / agent prompts: use a $CASE_ROOT placeholder or resolve at render time
  • Shell scripts: derive CASE_REPO from $CASE_ROOT or $(dirname "$0")/.. instead of hardcoding
  • The orchestrator code already does this — the docs just need to catch up

3. Per-run task isolation

  • Use run-scoped directories or file locks to prevent concurrent writes to the same .task.json
  • Atomic task ID generation (lock file or DB-backed counter instead of counting .md files)
  • Scoped .case/ markers per worktree rather than per repo root

4. Consolidate .case/ marker approach

The recent refactor (3aa5f23) consolidated .case-* markers into .case/<task-slug>/. Extend this so each worktree gets its own marker scope, preventing cross-agent marker conflicts.

Context

The ideation docs already reference worktree support as future work:

  • docs/ideation/orchestrator-refinement/spec-phase-2.md mentions --worktree flags
  • docs/ideation/case-multi-agent/contract.md references agent isolation

This issue is about actually delivering on that — making worktree isolation the default rather than an opt-in flag.

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