Orchestrata Ultimate / Specs / 064-git-worktree-tools

064-git-worktree-tools: Git Worktree Tools

This specification defines the Git Worktree Tools for the Orchestrata Ultimate system, providing capabilities to manage Git worktrees for parallel development workflows. The tools enable entering existing worktrees, creating new worktrees with optional branch creation, and exiting worktrees to return to the parent repository context.

At a glance

Item Value
Spec directory specs/064-git-worktree-tools/
Status line in the spec Complete
Requirement IDs defined 54
With a @traces citation in src/ 50 (92.6%)
With a @traces citation in tests/ 0 (0.0%)
Tracked files 3
RTM page 064-git-worktree-tools

Reading this spec

This spec defines the Git worktree tools, which let agents and developers work on several features or fixes in parallel without switching branches in one working directory. Switching branches in place is disruptive and can lose uncommitted changes; Git worktrees let several working directories share one repository. The spec names two tools, EnterWorktreeTool (enter an existing worktree, or create a new one with an optional new branch) and ExitWorktreeTool (return to the main repository), and adds worktree discovery and validation, branch protection and conflict handling. Repository initialization and remote operations are explicitly out of scope.

The five user stories are entering an existing worktree, creating and entering a new one, exiting to the main repository, listing available worktrees and protected branch enforcement. The 54 requirement IDs (REQ-064-NNN) mostly restate the numbered functional requirements in order: the worktree path is a required parameter, an optional branch parameter creates a branch, resolved paths are normalized, the previous worktree is stored for restoration, exiting updates the session working directory to the main repository, force exit is supported, creation runs git worktree add, and branch names are validated. A group of security requirements (REQ-064-SEC-nnn) makes main, master, develop and HEAD protected by default so no worktree is created on them, lets the caller supply its own protected-branch list, and supports glob patterns through fnmatch.

The code is in the worktree tools module. The requirements traceability matrix lists each ID. The spec's own status line reads Complete and it tracks 3 files. Measured coverage is 50 of 54 requirements cited by at least one @traces in src/ (92.6%), spread over 1 module; the module citing the most of them is orchestrata_ultimate/tools/worktree_tools (50 requirements). In tests/, 0 requirements are cited by a test-side @traces. 4 requirements have no citing symbol; the behaviour may still exist in code that was never annotated.

Requirements

Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.

ID Done Requirement Traced by
REQ-064-001 yes (FR-001) Tool must accept worktree path as required parameter 1
REQ-064-002 yes (FR-002) Tool must validate path exists on filesystem 2
REQ-064-003 yes (FR-003) Tool must verify path is a registered git worktree 2
REQ-064-004 yes (FR-004) Tool must update session working directory context (in-tool session_id state — see fork note above) 2
REQ-064-005 yes (FR-005) Tool must return worktree metadata on success 2
REQ-064-006 yes (FR-006) Tool must support both absolute and relative paths 1
REQ-064-007 yes (FR-007) Tool must accept optional branch parameter for creation 1
REQ-064-008 yes (FR-008) Tool must accept create flag to enable worktree creation 1
REQ-064-009 yes (FR-009) Tool must support create_branch flag for branch creation 1
REQ-064-010 yes (FR-010) Tool must support start_point for new branch creation 1
REQ-064-011 yes (FR-011) Relative paths must be resolved relative to the anchor directory 1
REQ-064-012 yes (FR-012) Path resolution must handle .. and . components 1
REQ-064-013 yes (FR-013) Resolved paths must be normalized (no redundant separators) 1
REQ-064-014 yes (FR-014) Tool must reject paths outside repository structure 3
REQ-064-015 yes (FR-015) Tool must verify the path is a registered worktree of the parent repo (via git worktree list --porcelain membership, not manual .git-file parsing — functionally equivalent, see fork note) 2
REQ-064-016 yes (FR-016) Tool must verify worktree is listed in git worktree list 3
REQ-064-017 yes (FR-017) Tool must handle both main worktree and auxiliary worktrees 2
REQ-064-018 yes (FR-018) Tool must detect and report locked worktrees 3
REQ-064-019 yes (FR-019, 1st occurrence) Tool must store previous worktree info for potential restoration 1
REQ-064-020 yes (FR-019, 2nd occurrence) Tool must update the tracked branch context 1
REQ-064-021 yes (FR-020) Tool must update worktree path in session state 1
REQ-064-022 no (FR-021) Tool must preserve other session state during transition — not implemented: no broader session runtime exists in this codebase to preserve state for; the self-contained _SessionWorktreeState only models worktree-relevant fields (see module fork note) none
REQ-064-023 yes (FR-022) Tool must determine parent repository path 2
REQ-064-024 yes (FR-023) Tool must validate main worktree is accessible 1
REQ-064-025 yes (FR-024) Tool must update session CWD to main repository 1
REQ-064-026 yes (FR-025) Tool must clear worktree-specific context 1
REQ-064-027 yes (FR-026) Tool must be idempotent when already in main worktree 1
REQ-064-028 yes (FR-027) Tool must return main worktree metadata on success 1
REQ-064-029 yes (FR-028) Tool must check for uncommitted changes before exit 1
REQ-064-030 yes (FR-029) Tool must support stash uncommitted changes option 1
REQ-064-031 yes (FR-030) Tool must support force exit option 1
REQ-064-032 yes (FR-031) Tool must warn user of uncommitted changes (via the UNCOMMITTED_CHANGES error's details/recovery_suggestions) 2
REQ-064-033 yes (FR-032) Tool must locate the parent repository (via git worktree list, not manual .git-file parsing — see REQ-064-015 note) 1
REQ-064-034 no (FR-033) Tool must handle both gitdir and gitdir: <prefix> .git-file formats — not implemented: no manual .git file is read; worktree bookkeeping is delegated entirely to the git binary, so this literal format-handling requirement does not apply to this implementation none
REQ-064-035 yes (FR-034) Tool must work when called from a nested directory (git itself walks up from any nested cwd/anchor to find the enclosing worktree) 1
REQ-064-036 yes (FR-035) Tool must create worktree directory 2
REQ-064-037 yes (FR-036) Tool must execute git worktree add command 2
REQ-064-038 yes (FR-037) Tool must create branch if specified and doesn't exist 2
REQ-064-039 yes (FR-038) Tool must support specifying start point for new branch none
REQ-064-040 no (FR-039) Tool must handle branch from remote tracking — not implemented/unverified: start_point is passed through to git worktree add unmodified (so a remote ref like origin/foo works via git itself), but there is no dedicated remote-tracking resolution or test (no remote is available in the throwaway test repos) — MVP scope cut none
REQ-064-041 yes (FR-040) Tool must reject an existing populated target directory 2
REQ-064-042 yes (FR-041) Tool must reject duplicate worktree for existing branch 2
REQ-064-043 yes (FR-042) Tool must validate branch name format 3
REQ-064-044 yes (FR-043) Tool must validate target path format 1
REQ-064-045 yes (FR-044) Tool must execute git worktree list 2
REQ-064-046 yes (FR-045) Tool must parse output to extract worktree info 3
REQ-064-047 yes (FR-046) Tool must enrich with branch and HEAD information 3
REQ-064-048 yes (FR-047) Tool must identify the main worktree 2
REQ-064-049 yes (FR-048) Tool must return a list with a single entry for a single-worktree repo 2
REQ-064-SEC-001 yes main/master/develop/HEAD are protected by default and cannot have worktrees created on them 3
REQ-064-SEC-002 yes Protected branches are configurable via the caller-supplied protected_branches parameter 3
REQ-064-SEC-003 yes Protected-branch matching supports glob patterns (*, ?, [abc]) via fnmatch 3
REQ-064-EXT-001 yes exit_worktree supports remove=true to delete the exited worktree via git worktree remove (with --force when the exit itself was forced or stashed) 1
REQ-064-EXT-002 yes exit_worktree supports prune=true to garbage-collect abandoned/orphaned worktree administrative state via git worktree prune 1

Code that traces this spec

Module Symbols Requirements
orchestrata_ultimate/tools/worktree_tools 14 50

Checklists

checklists/requirements.md

The requirement list above comes from this file; 51 of 54 checkbox items are ticked.

Other tracked files

Full spec text

Verbatim from specs/064-git-worktree-tools/spec.md; headings are pushed down two levels.

SPEC-064: Git Worktree Tools

Metadata


Overview

1.1 Purpose

This specification defines the Git Worktree Tools for the Orchestrata Ultimate system, providing capabilities to manage Git worktrees for parallel development workflows. The tools enable entering existing worktrees, creating new worktrees with optional branch creation, and exiting worktrees to return to the parent repository context.

1.2 Problem Statement

Developers often need to work on multiple features or bug fixes simultaneously. Switching between branches in a single working directory is disruptive and can lead to uncommitted changes being lost. Git worktrees provide a solution by allowing multiple working directories to share a single repository, enabling parallel work on different branches without directory switching.

1.3 Scope

The Git Worktree Tools provide:

1.4 Non-Scope

User Scenarios

2.1 US-001: Enter Existing Worktree

As a developer
I want to enter an existing git worktree directory
So that I can continue working on a feature branch in an isolated environment

Preconditions:

Flow:

  1. User invokes EnterWorktreeTool with worktree path
  2. Tool validates the path points to a valid worktree
  3. Tool verifies worktree is registered in parent repository
  4. Tool updates session context with new working directory
  5. Tool returns success with worktree metadata

Postconditions:

Acceptance Criteria:


2.2 US-002: Create and Enter New Worktree

As a developer
I want to create a new worktree for a feature branch
So that I can start developing a new feature in isolation

Preconditions:

Flow:

  1. User invokes EnterWorktreeTool with worktree path, branch name, and create=true
  2. Tool validates target directory does not exist
  3. Tool checks branch doesn't already have a worktree
  4. Tool runs git worktree add <path> <branch>
  5. Tool creates branch if create_branch=true and branch doesn't exist
  6. Tool updates session context with new working directory
  7. Tool returns success with worktree metadata

Postconditions:

Acceptance Criteria:


2.3 US-003: Exit Worktree to Main Repository

As a developer
I want to exit the current worktree and return to main repository
So that I can switch context to the primary branch

Preconditions:

Flow:

  1. User invokes ExitWorktreeTool
  2. Tool determines parent repository path
  3. Tool verifies main worktree exists and is accessible
  4. Tool updates session context with main repository CWD
  5. Tool clears worktree-specific state
  6. Tool returns success with main repository path

Postconditions:

Acceptance Criteria:


2.4 US-004: List Available Worktrees

As a developer
I want to see all available worktrees in the repository
So that I can choose which worktree to enter

Preconditions:

Flow:

  1. User invokes ListWorktreesTool
  2. Tool runs git worktree list to get all worktrees
  3. Tool parses output and enriches with branch/HEAD info
  4. Tool returns list of worktrees with metadata

Postconditions:

Acceptance Criteria:


2.5 US-005: Protected Branch Enforcement

As a project maintainer
I want to prevent worktree creation on protected branches
So that I can maintain branch integrity and compliance

Preconditions:

Flow:

  1. User attempts to create worktree with protected branch
  2. Tool checks branch against protected list
  3. Tool rejects creation with appropriate error
  4. Tool logs security event

Postconditions:

Acceptance Criteria:


Terminology

4.1 Worktree

A Git worktree is a separate working directory that shares the same Git repository with other worktrees. Each worktree can check out a different branch.

4.2 Main Worktree

The primary working directory created when a Git repository is initialized. Stored at the repository root.

4.3 Auxiliary Worktree

A secondary working directory created using git worktree add. Stored separately from the main repository.

4.4 Worktree Directory

The filesystem path where an auxiliary worktree's files are stored.

4.5 Parent Repository

The main Git repository that owns and manages all worktrees.

4.6 Protected Branch

A branch on which worktree creation is forbidden to maintain repository integrity.


Non-Functional Requirements

5.1 Performance Requirements
Requirement Target Measurement
Worktree creation time < 2 seconds Time from request to success for local repositories
Worktree entry time < 100ms Time to update session context
Worktree listing time < 500ms Time to execute git worktree list and parse output
Memory usage < 50MB Maximum additional memory per worktree operation
5.2 Scalability Requirements
Requirement Target
Maximum worktrees per repository 50
Maximum concurrent operations 10
Supported repository size Up to 10GB
5.3 Reliability Requirements
Requirement Target
Availability 99.9% uptime
Mean Time Between Failures 720 hours
Mean Time To Recovery < 5 minutes
5.4 Usability Requirements

Technical Design

6.1 Architecture Overview

The Git Worktree Tools follow a layered architecture:

┌─────────────────────────────────────┐
│         Session Layer              │
│    (SessionState Management)        │
└─────────────────┬───────────────────┘
                  │
┌─────────────────▼───────────────────┐
│        Worktree Layer              │
│   (EnterWorktreeTool, ExitTool)    │
└─────────────────┬───────────────────┘
                  │
┌─────────────────▼───────────────────┐
│         Git Layer                  │
│      (GitPython API)               │
└─────────────────────────────────────┘
6.2 State Management

Session state tracks:

6.3 Context Switching Flow
Request → Validate → Execute → Update Context → Response
    ↓         ↓         ↓           ↓            ↓
  Input    Git    Command    Session      Output
 Validation Checks   Execution   Update     Formatting
6.4 Protected Branch Enforcement

Protected branch checks occur before worktree creation:

  1. Parse protected branch configuration
  2. Compile glob patterns to regex
  3. Match branch name against patterns
  4. Log security event if match found
  5. Reject with PROTECTED_BRANCH error

Examples

7.1 Creating a Feature Branch Worktree

Request:

result = await tool.execute(
    worktreePath="/project/worktrees/feature-auth",
    branch="feature/authentication",
    create=True,
    createBranch=True,
    startPoint="main"
)

Response:

{
  "success": true,
  "worktree": {
    "path": "/project/worktrees/feature-auth",
    "branch": "feature/authentication",
    "head": "abc123def456789012345678901234567890abcd",
    "isMain": false,
    "isBare": false,
    "locked": false,
    "lockReason": null
  },
  "created": true,
  "message": "Created and entered worktree for feature/authentication"
}
7.2 Entering an Existing Worktree

Request:

result = await tool.execute(
    worktreePath="../worktrees/hotfix-login"
)

Response:

{
  "success": true,
  "worktree": {
    "path": "/project/worktrees/hotfix-login",
    "branch": "hotfix/login-bug",
    "head": "def456abc789012345678901234567890abcd123",
    "isMain": false,
    "isBare": false,
    "locked": false,
    "lockReason": null
  },
  "previousWorktree": {
    "path": "/project",
    "branch": "main",
    "head": "abc123def456789012345678901234567890abcd",
    "isMain": true
  },
  "created": false,
  "message": "Entered existing worktree for hotfix/login-bug"
}
7.3 Handling Protected Branch Error

Request:

result = await tool.execute(
    worktreePath="/project/worktrees/main-backup",
    branch="main",
    create=True
)

Response:

{
  "success": false,
  "error": "Cannot create worktree on protected branch: 'main'",
  "code": "PROTECTED_BRANCH",
  "details": {
    "branch": "main",
    "protectionReason": "Main branch must remain clean for production deployments"
  },
  "recoverySuggestions": [
    "Create a feature branch instead: git checkout -b feature/your-feature",
    "Work on the feature branch in a worktree"
  ]
}
7.4 Listing All Worktrees

Request:

result = await list_tool.execute(verbose=True)

Response:

{
  "success": true,
  "worktrees": [
    {
      "path": "/project",
      "branch": "main",
      "head": "abc123def456789012345678901234567890abcd",
      "isMain": true
    },
    {
      "path": "/project/worktrees/feature-auth",
      "branch": "feature/authentication",
      "head": "abc123def456789012345678901234567890abcd",
      "isMain": false
    }
  ],
  "count": 2,
  "message": "Found 2 worktrees"
}

Data Models

3.1 WorktreeInfo

Schema for representing a Git worktree:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://orchestrata.ult/worktree-info",
  "title": "WorktreeInfo",
  "description": "Represents a Git worktree with its metadata",
  "type": "object",
  "required": ["path", "branch", "head", "isMain"],
  "properties": {
    "path": {
      "type": "string",
      "description": "Absolute path to the worktree directory",
      "examples": ["/project/worktrees/feature-auth"],
      "pattern": "^/"
    },
    "branch": {
      "type": "string",
      "description": "Name of the branch checked out in this worktree",
      "examples": ["feature/authentication"],
      "pattern": "^[a-zA-Z0-9_./-]+$"
    },
    "head": {
      "type": "string",
      "description": "Full SHA-1 hash of the current HEAD commit",
      "examples": ["abc123def456789012345678901234567890abcd"],
      "pattern": "^[a-f0-9]{40}$"
    },
    "isMain": {
      "type": "boolean",
      "description": "Whether this is the main worktree (primary working directory)",
      "default": false
    },
    "isBare": {
      "type": "boolean",
      "description": "Whether this is a bare worktree",
      "default": false
    },
    "locked": {
      "type": "boolean",
      "description": "Whether the worktree is locked",
      "default": false
    },
    "lockReason": {
      "type": ["string", "null"],
      "description": "Reason for locking if locked",
      "examples": ["reason: ongoing work"]
    }
  }
}
3.2 EnterWorktreeRequest

Input schema for entering a worktree:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://orchestrata.ult/enter-worktree-request",
  "title": "EnterWorktreeRequest",
  "description": "Request parameters for entering a Git worktree",
  "type": "object",
  "properties": {
    "worktreePath": {
      "type": "string",
      "description": "Path to the worktree (absolute or relative to current directory)",
      "examples": ["../worktrees/feature-auth", "/project/worktrees/feature-auth"],
      "minLength": 1
    },
    "branch": {
      "type": ["string", "null"],
      "description": "Branch name for creating new worktree (required if create is true)",
      "examples": ["feature/new-login"],
      "pattern": "^[a-zA-Z0-9_./-]+$"
    },
    "create": {
      "type": "boolean",
      "description": "Whether to create the worktree if it doesn't exist",
      "default": false
    },
    "createBranch": {
      "type": "boolean",
      "description": "Whether to create the branch if it doesn't exist",
      "default": false
    },
    "startPoint": {
      "type": ["string", "null"],
      "description": "Commit or branch to start from when creating new branch",
      "examples": ["HEAD~3", "main", "abc123"],
      "pattern": "^[a-zA-Z0-9_./~-]+$"
    },
    "force": {
      "type": "boolean",
      "description": "Force creation even if worktree path exists (dangerous)",
      "default": false
    }
  },
  "required": ["worktreePath"],
  "additionalProperties": false
}
3.3 ExitWorktreeRequest

Input schema for exiting a worktree:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://orchestrata.ult/exit-worktree-request",
  "title": "ExitWorktreeRequest",
  "description": "Request parameters for exiting a Git worktree",
  "type": "object",
  "properties": {
    "force": {
      "type": "boolean",
      "description": "Force exit even if there are uncommitted changes in current worktree",
      "default": false
    },
    "stashChanges": {
      "type": "boolean",
      "description": "Automatically stash uncommitted changes before exiting",
      "default": false
    }
  },
  "additionalProperties": false
}
3.4 WorktreeListRequest

Input schema for listing worktrees:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://orchestrata.ult/worktree-list-request",
  "title": "WorktreeListRequest",
  "description": "Request parameters for listing Git worktrees",
  "type": "object",
  "properties": {
    "includePrunable": {
      "type": "boolean",
      "description": "Include prunable (orphan) worktrees in the list",
      "default": false
    },
    "verbose": {
      "type": "boolean",
      "description": "Include detailed information (HEAD, branch details)",
      "default": false
    }
  },
  "additionalProperties": false
}
3.5 EnterWorktreeResponse

Response schema for entering a worktree:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://orchestrata.ult/enter-worktree-response",
  "title": "EnterWorktreeResponse",
  "description": "Response from entering a Git worktree",
  "type": "object",
  "required": ["success", "worktree"],
  "properties": {
    "success": {
      "type": "boolean",
      "description": "Whether the operation succeeded"
    },
    "worktree": {
      "$ref": "#/$defs/WorktreeInfo"
    },
    "previousWorktree": {
      "$ref": "#/$defs/WorktreeInfo",
      "description": "Previous worktree information (if any)"
    },
    "created": {
      "type": "boolean",
      "description": "Whether a new worktree was created"
    },
    "message": {
      "type": "string",
      "description": "Human-readable status message"
    }
  },
  "$defs": {
    "WorktreeInfo": {
      "$ref": "https://orchestrata.ult/worktree-info"
    }
  }
}
3.6 ErrorResponse

Standard error response schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://orchestrata.ult/error-response",
  "title": "ErrorResponse",
  "description": "Standard error response for worktree operations",
  "type": "object",
  "required": ["success", "error", "code"],
  "properties": {
    "success": {
      "type": "boolean",
      "const": false
    },
    "error": {
      "type": "string",
      "description": "Human-readable error message"
    },
    "code": {
      "type": "string",
      "description": "Machine-readable error code",
      "examples": ["WORKTREE_NOT_FOUND", "PROTECTED_BRANCH", "INVALID_PATH"]
    },
    "details": {
      "type": ["object", "null"],
      "description": "Additional error context"
    },
    "recoverySuggestions": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Suggestions for recovering from the error"
    }
  }
}

Functional Requirements

4.1 EnterWorktreeTool
4.1.1 Core Functionality
ID Requirement Priority
FR-001 Tool must accept worktree path as required parameter MUST
FR-002 Tool must validate path exists on filesystem MUST
FR-003 Tool must verify path is a registered git worktree MUST
FR-004 Tool must update session working directory context MUST
FR-005 Tool must return worktree metadata on success MUST
FR-006 Tool must support both absolute and relative paths MUST
FR-007 Tool must accept optional branch parameter for creation SHOULD
FR-008 Tool must accept create flag to enable worktree creation SHOULD
FR-009 Tool must support createBranch flag for branch creation SHOULD
FR-010 Tool must support startPoint for new branch creation SHOULD
4.1.2 Path Resolution
ID Requirement Priority
FR-011 Relative paths must be resolved relative to current CWD MUST
FR-012 Path resolution must handle .. and . components MUST
FR-013 Resolved paths must be normalized (no redundant separators) SHOULD
FR-014 Tool must reject paths outside repository structure MUST
4.1.3 Worktree Validation
ID Requirement Priority
FR-015 Tool must verify .git file points to parent repo MUST
FR-016 Tool must verify worktree is listed in git worktree list MUST
FR-017 Tool must handle both main worktree and auxiliary worktrees MUST
FR-018 Tool must detect and report locked worktrees SHOULD
4.1.4 Context Management
ID Requirement Priority
FR-019 Tool must store previous CWD for potential restoration MUST
FR-019 Tool must update git branch context MUST
FR-020 Tool must update worktree path in session state MUST
FR-021 Tool must preserve other session state during transition MUST
4.2 ExitWorktreeTool
4.2.1 Core Functionality
ID Requirement Priority
FR-022 Tool must determine parent repository path MUST
FR-023 Tool must validate main worktree is accessible MUST
FR-024 Tool must update session CWD to main repository MUST
FR-025 Tool must clear worktree-specific context MUST
FR-026 Tool must be idempotent when already in main worktree SHOULD
FR-027 Tool must return main worktree metadata on success MUST
4.2.2 Safety Checks
ID Requirement Priority
FR-028 Tool must check for uncommitted changes before exit SHOULD
FR-029 Tool must support stash uncommitted changes option SHOULD
FR-030 Tool must support force exit option SHOULD
FR-031 Tool must warn user of uncommitted changes SHOULD
4.2.3 Parent Repository Detection
ID Requirement Priority
FR-032 Tool must read .git file to find parent repo MUST
FR-033 Tool must handle both gitdir and gitdir:prefix formats MUST
FR-034 Tool must work when called from nested directory MUST
4.3 CreateWorktreeTool
4.3.1 Core Functionality
ID Requirement Priority
FR-035 Tool must create worktree directory MUST
FR-036 Tool must execute git worktree add command MUST
FR-037 Tool must create branch if specified and doesn't exist SHOULD
FR-038 Tool must support specifying start point for new branch SHOULD
FR-039 Tool must handle branch from remote tracking SHOULD
4.3.2 Validation
ID Requirement Priority
FR-040 Tool must reject existing populated target directory MUST
FR-041 Tool must reject duplicate worktree for existing branch MUST
FR-042 Tool must validate branch name format MUST
FR-043 Tool must validate target path format MUST
4.4 ListWorktreesTool
4.4.1 Core Functionality
ID Requirement Priority
FR-044 Tool must execute git worktree list MUST
FR-045 Tool must parse output to extract worktree info MUST
FR-046 Tool must enrich with branch and HEAD information SHOULD
FR-047 Tool must identify main worktree MUST
FR-048 Tool must return list with single entry for single worktree repo MUST

Error Conditions

10.1 Error Code Reference
ID Code HTTP Status Description Handling
ERR-001 NOT_A_GIT_REPO 400 Current directory is not in a git repository Exit with error message
ERR-002 WORKTREE_NOT_FOUND 404 Specified worktree does not exist Suggest creating with create=true
ERR-003 WORKTREE_NOT_REGISTERED 400 Path exists but not registered as worktree Suggest proper worktree creation
ERR-004 WORKTREE_ALREADY_EXISTS 409 Worktree already exists at path Return existing worktree info
ERR-005 BRANCH_ALREADY_HAS_WORKTREE 409 Branch already has a worktree Return existing worktree path
ERR-006 BRANCH_NOT_FOUND 404 Specified branch does not exist Suggest creating with createBranch=true
ERR-007 PROTECTED_BRANCH 403 Attempt to create worktree on protected branch Explain protection policy
ERR-008 INVALID_PATH 400 Path format is invalid Provide valid path format
ERR-009 PATH_OUTSIDE_REPO 403 Path would create worktree outside repo bounds Suggest valid location
ERR-010 UNCOMMITTED_CHANGES 409 Current worktree has uncommitted changes Offer stash or force options
ERR-011 MAIN_WORKTREE_UNAVAILABLE 500 Cannot determine or access main worktree Log error, return guidance
ERR-012 WORKTREE_LOCKED 423 Worktree is locked Provide lock reason if available
ERR-013 PERMISSION_DENIED 403 Insufficient permissions Check user permissions
ERR-014 GIT_COMMAND_FAILED 500 Underlying git command failed Log git error, return message
ERR-015 INVALID_BRANCH_NAME 400 Branch name contains invalid characters Provide valid branch name format
10.2 Detailed Error Handling
10.2.1 ERR-001: NOT_A_GIT_REPO

Error ID: ERR-001

Condition: Current directory is not inside a git repository

Detection:

git rev-parse --is-inside-work-tree
# Returns "false" if not in repo

Response:

{
  "success": false,
  "error": "Not a git repository: /current/path",
  "code": "NOT_A_GIT_REPO",
  "recoverySuggestions": [
    "Navigate to a git repository directory",
    "Initialize a new git repository if needed: git init"
  ]
}
10.2.2 ERR-002: WORKTREE_NOT_FOUND

Error ID: ERR-002

Condition: Specified worktree path does not exist

Detection:

os.path.exists(request.worktreePath) == False

Response:

{
  "success": false,
  "error": "Worktree not found at path: /project/worktrees/feature-auth",
  "code": "WORKTREE_NOT_FOUND",
  "details": {
    "requestedPath": "/project/worktrees/feature-auth"
  },
  "recoverySuggestions": [
    "Create the worktree first: EnterWorktreeTool with create=true",
    "List available worktrees to see existing ones"
  ]
}
10.2.3 ERR-003: WORKTREE_NOT_REGISTERED

Error ID: ERR-003

Condition: Path exists but is not a registered git worktree

Detection:

# Check .git file points to worktree directory
git worktree list --porcelain | grep -q <path> == False

Response:

{
  "success": false,
  "error": "Path exists but is not a registered git worktree: /some/path",
  "code": "WORKTREE_NOT_REGISTERED",
  "recoverySuggestions": [
    "Use git worktree add to create a proper worktree",
    "This may be a regular directory that was accidentally created"
  ]
}
10.2.4 ERR-004: WORKTREE_ALREADY_EXISTS

Error ID: ERR-004

Condition: Worktree already exists at specified path

Detection:

os.path.exists(request.worktreePath) == True
# AND registered in git

Response:

{
  "success": false,
  "error": "Worktree already exists at: /project/worktrees/feature-auth",
  "code": "WORKTREE_ALREADY_EXISTS",
  "details": {
    "existingPath": "/project/worktrees/feature-auth"
  },
  "recoverySuggestions": [
    "Use EnterWorktreeTool without create flag to enter existing worktree",
    "Choose a different path for new worktree"
  ]
}
10.2.5 ERR-005: BRANCH_ALREADY_HAS_WORKTREE

Error ID: ERR-005

Condition: Attempting to create worktree for branch that already has one

Detection:

git worktree list | grep <branch>  # Branch has worktree

Response:

{
  "success": false,
  "error": "Branch 'feature/auth' already has a worktree",
  "code": "BRANCH_ALREADY_HAS_WORKTREE",
  "details": {
    "branch": "feature/auth",
    "existingWorktree": "/project/worktrees/feature-auth"
  },
  "recoverySuggestions": [
    "Enter the existing worktree: EnterWorktreeTool(worktree_path='/project/worktrees/feature-auth')",
    "Delete the existing worktree first if you want to create a new one"
  ]
}
10.2.6 ERR-006: BRANCH_NOT_FOUND

Error ID: ERR-006

Condition: Specified branch does not exist

Detection:

git show-ref --verify --quiet refs/heads/<branch> == False

Response:

{
  "success": false,
  "error": "Branch 'feature/nonexistent' does not exist",
  "code": "BRANCH_NOT_FOUND",
  "details": {
    "branch": "feature/nonexistent"
  },
  "recoverySuggestions": [
    "Enable createBranch=true to create the branch",
    "Specify a valid existing branch name",
    "Check branch name for typos"
  ]
}
10.2.7 ERR-007: PROTECTED_BRANCH

Error ID: ERR-007

Condition: Attempt to create worktree on protected branch

Detection:

branch in PROTECTED_BRANCHES  # main, master, release/*, etc.

Response:

{
  "success": false,
  "error": "Cannot create worktree on protected branch: 'main'",
  "code": "PROTECTED_BRANCH",
  "details": {
    "branch": "main",
    "protectionReason": "Main branch must remain clean for production deployments"
  },
  "recoverySuggestions": [
    "Create a feature branch instead: git checkout -b feature/your-feature",
    "Work on the feature branch in a worktree"
  ]
}
10.2.8 ERR-008: INVALID_PATH

Error ID: ERR-008

Condition: Path format is invalid

Detection:

# Contains null bytes, too long, or invalid characters
# os.path.normpath raises exception

Response:

{
  "success": false,
  "error": "Invalid path format: path contains invalid characters",
  "code": "INVALID_PATH",
  "details": {
    "providedPath": "/path/with\0null"
  },
  "recoverySuggestions": [
    "Provide a valid absolute or relative path",
    "Avoid special characters: null bytes, newlines"
  ]
}
10.2.9 ERR-009: PATH_OUTSIDE_REPO

Error ID: ERR-009

Condition: Worktree path would be outside repository structure

Detection:

# Resolve path and check it's within repo root
not path.resolve().is_within(repo_root)

Response:

{
  "success": false,
  "error": "Worktree path is outside repository bounds",
  "code": "PATH_OUTSIDE_REPO",
  "details": {
    "providedPath": "/tmp/worktree",
    "repoRoot": "/project"
  },
  "recoverySuggestions": [
    "Create worktree within repository: /project/worktrees/feature-name",
    "Use relative path from repository root"
  ]
}
10.2.10 ERR-010: UNCOMMITTED_CHANGES

Error ID: ERR-010

Condition: Current worktree has uncommitted changes

Detection:

git diff-index --quiet HEAD == False
git diff --stat == "" == False

Response:

{
  "success": false,
  "error": "Cannot exit worktree with uncommitted changes",
  "code": "UNCOMMITTED_CHANGES",
  "details": {
    "changedFiles": 3,
    "untrackedFiles": 1,
    "changes": [
      "M  modified_file.txt",
      "?? untracked.txt"
    ]
  },
  "recoverySuggestions": [
    "Commit your changes: git add . && git commit",
    "Stash changes: ExitWorktreeTool with stashChanges=true",
    "Force exit: ExitWorktreeTool with force=true (changes will remain)"
  ]
}

API Contracts

6.1 EnterWorktreeTool
6.1.1 Interface Definition
class EnterWorktreeTool(BaseTool):
    """Tool for entering or creating Git worktrees."""
    
    name: str = "EnterWorktreeTool"
    description: str = (
        "Enter an existing Git worktree or create a new one. "
        "Use this to switch to a different branch while maintaining "
        "an isolated working directory for parallel development."
    )
    version: str = "1.0.0"
    
    parameters: dict = {
        "type": "object",
        "properties": {
            "worktreePath": {
                "type": "string",
                "description": "Path to the worktree (absolute or relative). "
                              "If create=true, this is where the new worktree will be created.",
                "examples": [
                    "../worktrees/feature-auth",
                    "/project/worktrees/feature-auth",
                    "feature-branch"
                ]
            },
            "branch": {
                "type": ["string", "null"],
                "description": "Branch name to check out. Required if create=true.",
                "examples": ["feature/authentication", "bugfix/login-fix"],
                "default": None
            },
            "create": {
                "type": "boolean",
                "description": "Create worktree if it doesn't exist. Requires branch parameter.",
                "default": False
            },
            "createBranch": {
                "type": "boolean",
                "description": "Create branch if it doesn't exist. Requires create=true.",
                "default": False
            },
            "startPoint": {
                "type": ["string", "null"],
                "description": "Commit-ish (branch, tag, commit) to start new branch from. "
                              "Defaults to current HEAD if not specified.",
                "examples": ["HEAD~3", "v1.0.0", "main", "abc123def"],
                "default": None
            },
            "force": {
                "type": "boolean",
                "description": "Force creation even if directory exists (dangerous - may overwrite).",
                "default": False
            }
        },
        "required": ["worktreePath"],
        "additionalProperties": False
    }
    
    async def execute(
        self,
        worktreePath: str,
        branch: str | None = None,
        create: bool = False,
        createBranch: bool = False,
        startPoint: str | None = None,
        force: bool = False
    ) -> EnterWorktreeResponse:
        """Execute the worktree entry operation."""
        pass
6.1.2 Response Schema
class EnterWorktreeResponse(ToolResult):
    success: bool
    worktree: WorktreeInfo
    previousWorktree: WorktreeInfo | None = None
    created: bool = False
    message: str
6.1.3 Execution Flow
1. Validate current directory is in git repo
   └─> NOT_A_GIT_REPO if fails

2. Resolve worktreePath to absolute path
   └─> INVALID_PATH if resolution fails

3. If create == False:
   └─> Validate path exists
       └─> WORKTREE_NOT_FOUND if missing
   └─> Validate path is registered worktree
       └─> WORKTREE_NOT_REGISTERED if not

4. If create == True:
   └─> Validate branch parameter provided
       └─> BRANCH_REQUIRED if missing
   └─> Check protected branch list
       └─> PROTECTED_BRANCH if protected
   └─> Validate target directory doesn't exist (unless force)
       └─> WORKTREE_ALREADY_EXISTS if exists
   └─> Check branch doesn't already have worktree
       └─> BRANCH_ALREADY_HAS_WORKTREE if exists
   └─> Validate branch exists or createBranch == True
       └─> BRANCH_NOT_FOUND if missing and createBranch == False
   └─> Execute: git worktree add [options] <path> <branch>
       └─> GIT_COMMAND_FAILED if fails

5. Update session context:
   └─> Store previous CWD
   └─> Set new CWD to worktree path
   └─> Update branch context

6. Return EnterWorktreeResponse
6.2 ExitWorktreeTool
6.2.1 Interface Definition
class ExitWorktreeTool(BaseTool):
    """Tool for exiting current worktree to main repository."""
    
    name: str = "ExitWorktreeTool"
    description: str = (
        "Exit the current Git worktree and return to the main repository. "
        "This tool should be used when you want to switch context from a "
        "feature branch worktree back to the primary working directory."
    )
    version: str = "1.0.0"
    
    parameters: dict = {
        "type": "object",
        "properties": {
            "force": {
                "type": "boolean",
                "description": "Force exit even with uncommitted changes.",
                "default": False
            },
            "stashChanges": {
                "type": "boolean",
                "description": "Stash uncommitted changes before exiting.",
                "default": False
            }
        },
        "additionalProperties": False
    }
    
    async def execute(
        self,
        force: bool = False,
        stashChanges: bool = False
    ) -> ExitWorktreeResponse:
        """Execute the worktree exit operation."""
        pass
6.2.2 Response Schema
class ExitWorktreeResponse(ToolResult):
    success: bool
    mainWorktree: WorktreeInfo
    previousWorktree: WorktreeInfo | None = None
    message: str
    stashResult: str | None = None  # "stashed" or None
6.2.3 Execution Flow
1. Determine if currently in worktree vs main
   └─> Get .git file path

2. If already in main worktree:
   └─> Return success (idempotent)

3. Get main worktree path from .git file

4. Validate main worktree is accessible
   └─> MAIN_WORKTREE_UNAVAILABLE if fails

5. Check for uncommitted changes
   └─> If force == False and stashChanges == False:
       └─> Return UNCOMMITTED_CHANGES error
   └─> If stashChanges == True:
       └─> Execute: git stash
       └─> Store stash reference

6. Update session context:
   └─> Store previous worktree info
   └─> Set new CWD to main worktree path
   └─> Clear worktree-specific context

7. Return ExitWorktreeResponse
6.3 ListWorktreesTool
6.3.1 Interface Definition
class ListWorktreesTool(BaseTool):
    """Tool for listing all worktrees in a repository."""
    
    name: str = "ListWorktreesTool"
    description: str = "List all Git worktrees in the current repository."
    version: str = "1.0.0"
    
    parameters: dict = {
        "type": "object",
        "properties": {
            "verbose": {
                "type": "boolean",
                "description": "Include detailed information (HEAD, branch details).",
                "default": False
            },
            "includePrunable": {
                "type": "boolean",
                "description": "Include prunable (orphan) worktrees.",
                "default": False
            }
        },
        "additionalProperties": False
    }
    
    async def execute(
        self,
        verbose: bool = False,
        includePrunable: bool = False
    ) -> ListWorktreesResponse:
        """Execute the worktree listing operation."""
        pass
6.3.2 Response Schema
class ListWorktreesResponse(ToolResult):
    success: bool
    worktrees: list[WorktreeInfo]
    count: int
    message: str

Security Requirements

12.1 Branch Protection
12.1.1 Default Protected Branches

The following branches are protected by default and cannot have worktrees created on them:

12.1.2 Configuration

Protected branches can be configured via:

{
  "git": {
    "worktree": {
      "protectedBranches": [
        "main",
        "master",
        "release/*",
        "hotfix/*"
      ]
    }
  }
}
12.1.3 Pattern Matching

Branch protection supports glob patterns:

12.2 Conflict Handling
12.2.1 Worktree Branch Conflicts

If a branch already has a worktree, the tool must:

  1. Reject the creation request
  2. Return the existing worktree path
  3. Suggest entering the existing worktree
12.2.2 Path Conflicts

If the target path already exists:

  1. Check if it's a valid worktree
  2. If valid worktree: return existing info
  3. If not valid worktree: reject unless force=true
  4. If force=true: warn user, then proceed
12.2.3 Uncommitted Changes

When exiting a worktree with changes:

  1. Default: reject exit
  2. With stashChanges=true: auto-stash
  3. With force=true: allow exit, changes remain
12.3 Path Validation
12.3.1 Repository Bounds

Worktrees must be created within the repository structure:

12.3.2 Path Sanitization

All paths must be sanitized:

12.4 Audit Logging

All worktree operations must be logged:

{
  "timestamp": "2026-04-08T12:00:00Z",
  "event": "WORKTREE_CREATE",
  "user": "agent-001",
  "branch": "feature/auth",
  "path": "/project/worktrees/feature-auth",
  "success": true,
  "protectedBranchAttempt": false
}

Testing Requirements

Test Coverage Requirements
Category Minimum Coverage Target Coverage
Unit Tests 85% 95%
Integration Tests 100% 100%
Security Tests 100% 100%
Functional Testing Requirements
Requirement ID Description Test Type
TR-001 Enter existing worktree with valid path Integration
TR-002 Enter worktree with relative path resolution Integration
TR-003 Create new worktree with create=true Integration
TR-004 Create worktree with branch creation Integration
TR-005 Exit worktree returns to main repository Integration
TR-006 Exit from main worktree is idempotent Integration
TR-007 List worktrees returns all worktrees Integration
TR-008 Protected branch blocks worktree creation Security
TR-009 Path validation prevents directory traversal Security
TR-010 Invalid path returns appropriate error Unit
TR-011 Non-git directory returns NOT_A_GIT_REPO Unit
TR-012 Uncommitted changes blocks exit without force Integration
Security Testing Requirements
Requirement ID Description Test Type
TR-101 Main branch worktree creation blocked Security
TR-102 Master branch worktree creation blocked Security
TR-103 Release/* pattern blocks release branches Security
TR-104 Path outside repository rejected Security
TR-105 Branch with existing worktree blocked Security
TR-106 Protected branch attempts logged Security
Performance Testing Requirements
Requirement ID Description Threshold
TR-201 Worktree entry operation < 200ms
TR-202 Worktree exit operation < 100ms
TR-203 Worktree list operation < 500ms
TR-204 Concurrent worktree operations 10+
Test Environment Requirements
Requirement Specification
Python Version 3.11+
Git Version 2.30+
Test Repository Isolated git repo with worktrees
Test Isolation Each test runs independently
Test Execution Requirements

Testing

8.1 Unit Tests
8.1.1 EnterWorktreeTool Tests
Test ID Description Expected Result
UT-001 Enter with valid existing worktree Success with worktree info
UT-002 Enter with valid absolute path Success
UT-003 Enter with valid relative path Success with resolved path
UT-004 Enter non-existent worktree WORKTREE_NOT_FOUND
UT-005 Enter unregistered directory WORKTREE_NOT_REGISTERED
UT-006 Create new worktree with create=true Worktree created
UT-007 Create worktree without branch BRANCH_REQUIRED
UT-008 Create on protected branch PROTECTED_BRANCH
UT-009 Create on branch with existing worktree BRANCH_ALREADY_HAS_WORKTREE
UT-010 Create with invalid path INVALID_PATH
UT-011 Create with path outside repo PATH_OUTSIDE_REPO
UT-012 Enter in non-git directory NOT_A_GIT_REPO
8.1.2 ExitWorktreeTool Tests
Test ID Description Expected Result
UT-020 Exit from worktree to main Success
UT-021 Exit from main worktree Success (idempotent)
UT-022 Exit with uncommitted changes UNCOMMITTED_CHANGES
UT-023 Exit with stashChanges=true Changes stashed
UT-024 Exit with force=true Success (changes remain)
UT-025 Exit when main unavailable MAIN_WORKTREE_UNAVAILABLE
8.1.3 ListWorktreesTool Tests
Test ID Description Expected Result
UT-030 List with single worktree Return main only
UT-031 List with multiple worktrees Return all worktrees
UT-032 List with verbose=true Include HEAD details
UT-033 List in non-git repo NOT_A_GIT_REPO
8.2 Integration Tests
Test ID Description Expected Result
IT-001 Enter -> Exit roundtrip Return to original CWD
IT-002 Create -> Enter -> Exit workflow Complete workflow succeeds
IT-003 Multiple parallel worktrees All worktrees accessible
IT-004 Worktree with remote branch Remote tracking works
IT-005 Worktree with submodule Submodule handled correctly
8.3 End-to-End Tests
Test ID Description Expected Result
E2E-001 Full feature branch workflow User can complete workflow
E2E-002 Hotfix workflow Hotfix can be created and merged
E2E-003 Concurrent feature development Multiple features in parallel
8.4 Test Environment Requirements
@pytest.fixture
def git_repo(tmp_path):
    """Create a test git repository."""
    repo = tmp_path / "test_repo"
    repo.mkdir()
    subprocess.run(["git", "init"], cwd=repo, check=True)
    Path(repo / ".gitkeep").touch()
    subprocess.run(["git", "add", "."], cwd=repo, check=True)
    subprocess.run(["git", "commit", "-m", "Initial commit"], cwd=repo, check=True)
    return repo

@pytest.fixture
def worktree_dir(tmp_path):
    """Create a worktree directory."""
    wt = tmp_path / "worktrees" / "test"
    wt.mkdir(parents=True)
    return wt

Dependencies

9.1 Runtime Dependencies
Package Version Purpose
Python >=3.11 Runtime environment
Git >=2.30 Git operations
GitPython >=0.99 Git command wrapper
9.2 Internal Dependencies
Module Purpose
orchestrata.core.base Base tool class
orchestrata.git.repo Repository detection
orchestrata.git.context Git context management
orchestrata.session.state Session state management
orchestrata.config Configuration loading
orchestrata.logging Audit logging
9.3 External Dependencies
Dependency Version Purpose
pytest >=7.0 Testing framework
pytest-asyncio >=0.21 Async test support

Governance

15.1 Policy Enforcement
15.2 Audit Logging

All worktree operations must be logged:

async def log_worktree_action(action: str, details: dict):
    await audit_log({
        "event_type": "worktree",
        "action": action,
        "details": details,
        "timestamp": datetime.utcnow().isoformat()
    })
15.3 Compliance

Integration Points

16.1 Git Operations
Integration Module Purpose
Git Command Execution orchestrata.git.repo Execute git commands
Worktree Management orchestrata.git.worktree Native worktree operations
Branch Operations orchestrata.git.branch Branch CRUD operations
16.2 Session Management
Integration Module Purpose
CWD Management orchestrata.session.state Track current working directory
Context Updates orchestrata.session.context Update git context
History Stack orchestrata.session.history Track worktree navigation
16.3 Configuration
Integration Module Purpose
Config Loading orchestrata.config Load worktree settings
Protected Branches orchestrata.config.branch Branch protection rules
Logging orchestrata.logging Audit and operational logging

Success Criteria

17.1 Functional Success Criteria
Criterion Validation Method
EnterWorktreeTool can enter existing worktrees Manual test with valid worktree path
EnterWorktreeTool can create new worktrees Create worktree with create=true
ExitWorktreeTool returns to main repository Call from worktree, verify CWD
ListWorktreesTool returns all worktrees Compare with git worktree list
Protected branch enforcement blocks creation Attempt to create on main branch
17.2 Error Handling Success Criteria
Criterion Validation Method
Invalid paths return INVALID_PATH error Pass malformed paths
Non-existent worktrees return NOT_FOUND Pass non-existent path
Protected branches return PROTECTED_BRANCH Attempt creation on protected
Non-git directories return NOT_A_GIT_REPO Call from non-repo directory
17.3 Performance Success Criteria
Criterion Target Validation
Entry operation completes < 200ms Measure execution time
Exit operation completes < 100ms Measure execution time
List operation completes < 500ms Measure execution time
Memory overhead < 50MB Profile memory usage
17.4 Security Success Criteria
Criterion Validation Method
Protected branches cannot have worktrees Attempt creation, verify rejection
Unauthorized users cannot create worktrees Test with insufficient permissions
Audit log captures all operations Check logs after operations
Path validation prevents directory traversal Test with malicious paths
Unit Tests
class TestEnterWorktreeTool:
    async def test_enter_existing_worktree(self):
        tool = EnterWorktreeTool()
        result = await tool.execute(path="/path/to/worktree")
        assert result.success == True
        assert result.branch == "feature-branch"
    
    async def test_enter_nonexistent_worktree(self):
        tool = EnterWorktreeTool()
        result = await tool.execute(path="/nonexistent")
        assert result.success == False
        assert "not found" in result.error
Integration Tests
Test Coverage

Governance (PAM++)

Policy Enforcement
Audit Logging
async def log_worktree_action(action: str, details: dict):
    await audit_log({
        "event_type": "worktree",
        "action": action,
        "details": details
    })

Observability

Logging Requirements
  1. Component Logging
    • Log all major operations with appropriate log levels
    • Include correlation IDs for request tracing
    • Log performance metrics for critical operations
    • Log errors with full context for debugging
Metrics Requirements
  1. Performance Metrics
    • Operation duration histograms
    • Request/error rate counters
    • Resource utilization gauges
    • Business metrics relevant to domain
Tracing Requirements
  1. Distributed Tracing
    • Trace propagation across component boundaries
    • Span attributes for domain-specific context
    • Trace sampling based on operational needs
Alerting Requirements
  1. Critical Alerts
    • Error rate spikes
    • Performance degradation
    • Resource exhaustion
    • Business metric anomalies
Dashboard Requirements
  1. Operational Dashboard
    • Real-time system health
    • Performance trends
    • Error analysis
    • Resource monitoring

Revision History

Version Date Author Changes
1.0.0 2026-04-08 Mohamed Initial specification

References


End of SPEC-064