Skip to content

Worktree reuse matches environments from different local clones of the same remote #1183

@halindrome

Description

@halindrome

Summary

  • What broke: archon workflow run reuses a worktree created from a different local checkout of the same remote repository. Two separate local clones (e.g., /Sources/bugfix and /Sources/codespace) that share the same origin remote resolve to the same codebase_id, so findActiveByWorkflow returns isolation environments from the wrong local clone.
  • When it started: Present in current dev branch
  • Severity: major

Steps to Reproduce

  1. Clone the same repo to two different local directories:

    git clone git@example.com:org/repo.git ~/project-a
    git clone git@example.com:org/repo.git ~/project-b
  2. Run a workflow with --branch from the first directory:

    cd ~/project-a
    archon workflow run my-workflow --branch fix/issue-123 "issue 123"

    This creates a worktree under ~/.archon/worktrees/.../project-a/...

  3. Run the same workflow with the same --branch from the second directory:

    cd ~/project-b
    archon workflow run my-workflow --branch fix/issue-123 "issue 123"
  4. Actual: Archon reuses the worktree from step 2 (project-a), even though the user is working in project-b. The log shows worktree_reused pointing to project-a's worktree path.

  5. Expected: Archon creates a new worktree rooted under project-b, since the user invoked the workflow from a different local checkout.

Expected vs Actual

  • Expected: Each local clone is treated as a separate workspace. Worktrees are scoped to the local checkout they were created from.
  • Actual: Two local clones of the same remote share one codebase_id (derived from the remote URL). findActiveByWorkflow returns the first matching active environment regardless of which local checkout it belongs to.

User Flow

  User (in ~/project-b)        CLI (workflow.ts)           DB (isolation_environments)
  ─────────────────────        ─────────────────           ────────────────────────────
  runs workflow ──────────────▶ findRepoRoot(project-b)
                                → project-b
                                registerRepository(project-b)
                                → remote: git@...:org/repo
                                → codebase name: "org/repo"
                                → finds existing codebase_id  ◀── (registered by project-a)
                                findActiveByWorkflow(codebase_id, 'task', 'fix/issue-123')
                         [X]    → returns project-a's worktree ◀── matches codebase_id + branch
                                worktree_reused (wrong path!)
  workflow runs in project-a ◀─ uses wrong working directory

Environment

  • Platform: CLI
  • Database: SQLite
  • Running in worktree? Yes (Archon-managed worktrees)
  • OS: macOS Darwin 25.2.0

Logs

{"level":30,"module":"clone","owner":"git@ccsgitlab:corvexconnected","repo":"bugfix","path":"...bugfix/source","msg":"project_structure_created"}
{"level":30,"module":"cli.workflow","path":"/Users/.../worktrees/Sources/codespace/archon/task-fix-cvx-5921","msg":"worktree_reused"}
{"level":40,"module":"workflow.executor","codebaseName":"git@ccsgitlab:corvexconnected/corvex-workspace","msg":"codebase_name_not_owner_repo_format"}

Note: The user ran from /Sources/bugfix but the reused worktree is under /Sources/codespace.

Impact

  • Affected workflows/commands: Any archon workflow run --branch <name> when multiple local clones of the same remote exist
  • Reproduction rate: Always (deterministic when conditions are met)
  • Workaround available? Yes — omit --branch to force a fresh worktree with a timestamp-based name, or manually mark stale isolation environments as completed in the SQLite DB
  • Data loss risk? Yes — the workflow operates in the wrong directory. Code changes, commits, and MRs target the wrong checkout. In our case it created an MR in the wrong GitLab project with 88 unrelated files.

Scope

  • Package(s) likely involved: cli|core|isolation
  • Module (if known):
    • cli:commands/workflow.ts (lines 422-464) — worktree reuse lookup
    • core:db/isolation-environments.ts (findActiveByWorkflow) — query lacks local-path scoping
    • core:handlers/clone.ts (registerRepository) — two local clones get the same codebase_id

Root Cause Analysis

The remote_agent_codebases table uses the remote URL to derive the codebase identity. When two local directories point to the same remote, registerRepository returns the same codebase_id for both. The findActiveByWorkflow query then matches isolation environments across both local checkouts since it only filters on codebase_id + workflow_type + workflow_id.

Suggested Fix

The worktree reuse check in workflow.ts (line 426) should validate that existingEnv.working_path is rooted under the current cwd's worktree namespace before reusing it. For example:

if (existingEnv && (await provider.healthCheck(existingEnv.working_path))) {
  // Verify the worktree belongs to THIS local checkout, not a sibling clone
  const expectedPathPrefix = cwd; // or derive from the worktree naming convention
  if (!existingEnv.working_path.includes(basename(cwd))) {
    getLog().warn(
      { path: existingEnv.working_path, cwd },
      'worktree.reuse_different_checkout'
    );
    // Fall through to create a new worktree
  } else {
    // existing reuse logic
  }
}

Alternatively, registerRepository could incorporate the local path into the codebase identity (e.g., use default_cwd as part of the uniqueness constraint instead of just the remote URL), but this is a larger change with broader implications for the codebase registry.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions