# How to Troubleshoot Git Worktree Isolation in the Epic 1 Worktree Manager of aios-core

> Troubleshoot Git worktree isolation in aios-core. Learn to verify core-config.yaml, run diagnostic commands, and use the WorktreeManager API to fix conflicts.

- Repository: [SynkraAI/aios-core](https://github.com/synkraai/aios-core)
- Tags: how-to-guide
- Published: 2026-02-16

---

**To troubleshoot Git worktree isolation issues in SynkraAI/aios-core, verify your [`core-config.yaml`](https://github.com/SynkraAI/aios-core/blob/main/core-config.yaml) settings, run diagnostic commands via [`story-worktree-hooks.js`](https://github.com/SynkraAI/aios-core/blob/main/story-worktree-hooks.js), and use the `WorktreeManager` API to detect conflicts and clean up stale worktrees.**

The Epic 1 Worktree Manager in the SynkraAI/aios-core repository provides automated Git worktree isolation for story-based development, ensuring each feature branch operates in a dedicated directory under `.aios/worktrees`. When developers encounter "worktree already exists" errors, stale isolation directories, or merge conflicts, systematic troubleshooting using the built-in CLI hooks and JavaScript API restores repository integrity. This guide covers diagnostic steps and resolution strategies for common Git worktree isolation failures.

## Architecture of the Epic 1 Worktree Manager

The isolation system relies on four primary components that orchestrate Git worktree operations and enforce repository boundaries.

### Core Components

- **`WorktreeManager`** ([`.aios-core/infrastructure/scripts/worktree-manager.js`](https://github.com/SynkraAI/aios-core/blob/main/.aios-core/infrastructure/scripts/worktree-manager.js)): Low-level wrapper around `git worktree` commands handling creation, listing, removal, stale detection, conflict detection, and merge auditing.
- **[`story-worktree-hooks.js`](https://github.com/SynkraAI/aios-core/blob/main/story-worktree-hooks.js)** ([`.aios-core/infrastructure/scripts/story-worktree-hooks.js`](https://github.com/SynkraAI/aios-core/blob/main/.aios-core/infrastructure/scripts/story-worktree-hooks.js)): High-level CLI interface invoked on story state transitions (`onStoryStart`, `onStoryDone`), reading [`core-config.yaml`](https://github.com/SynkraAI/aios-core/blob/main/core-config.yaml) to decide auto-creation and auto-cleanup behavior.
- **[`auto-worktree.yaml`](https://github.com/SynkraAI/aios-core/blob/main/auto-worktree.yaml)** ([`.aios-core/development/workflows/auto-worktree.yaml`](https://github.com/SynkraAI/aios-core/blob/main/.aios-core/development/workflows/auto-worktree.yaml)): Declarative workflow executed by the AIOS engine that orchestrates extraction, pre-flight checks, creation, and status updates.
- **[`core-config.yaml`](https://github.com/SynkraAI/aios-core/blob/main/core-config.yaml)**: Project-wide configuration enabling worktree features, setting `maxWorktrees` (default 10), and `staleDays` (default 30).

### Isolation Guarantees

Each worktree receives a dedicated branch (`auto-claude/<storyId>`) and directory under `.aios/worktrees/<storyId>`. The manager records creation timestamps and uncommitted change counts, marking worktrees as *stale* after exceeding the `staleDays` threshold.

## Common Git Worktree Isolation Failures and Solutions

### "Worktree Already Exists" Errors

**Symptom:** The error `Worktree already exists` appears when starting a story.

**Root Cause:** A previous worktree was left behind from a failed run or manual interruption.

**Diagnostic Steps:**

1. Run `node .aios-core/infrastructure/scripts/story-worktree-hooks.js status <story-file>`.
2. Verify `hasWorktree: true` and note its `path`.

**Resolution:**

- If the worktree is still needed, creation is skipped (the `--force` flag is ignored for existing worktrees).
- If stale, run `node .aios-core/infrastructure/scripts/story-worktree-hooks.js done <story-file>` and select **cleanup**, or use `--keep-worktree` to preserve data while removing the Git worktree reference.

### Maximum Worktree Limit Reached

**Symptom:** Error `Maximum worktrees limit (10) reached` prevents new story isolation.

**Root Cause:** The repository contains the maximum number of active worktrees (`manager.getCount().total >= maxWorktrees`).

**Diagnostic Steps:**

1. Run `node .aios-core/infrastructure/scripts/story-worktree-hooks.js list` or use the manager's `list()` method in a Node REPL.
2. Identify stale or completed worktrees by checking timestamps.

**Resolution:**

Delete unwanted worktrees manually:

```bash
node .aios-core/infrastructure/scripts/story-worktree-hooks.js done <story-file> --keep-worktree

```

Then force remove via API:

```javascript
const WM = require('./.aios-core/infrastructure/scripts/worktree-manager');
const mgr = new WM(process.cwd());
await mgr.remove('STORY-42', {force: true});

```

Alternatively, enable `autoCleanup: true` in [`.aios-core/development/workflows/auto-worktree.yaml`](https://github.com/SynkraAI/aios-core/blob/main/.aios-core/development/workflows/auto-worktree.yaml) to automatically purge stale worktrees.

### Uncommitted Changes Blocking Cleanup

**Symptom:** `Worktree has X uncommitted changes` error during `onStoryDone` cleanup.

**Root Cause:** The worktree contains local edits that haven't been committed or stashed.

**Diagnostic Steps:**

1. Run `node .aios-core/infrastructure/scripts/story-worktree-hooks.js status <story-file>` to see `uncommittedChanges > 0`.
2. Run `git status` inside the worktree directory (`.aios/worktrees/<storyId>`).

**Resolution:**

Commit or stash changes before cleanup:

```bash
cd .aios/worktrees/STORY-42
git add .
git commit -m "WIP: save before worktree cleanup"

```

Alternatively, use the done hook with merge option first:

```bash
node .aios-core/infrastructure/scripts/story-worktree-hooks.js done <story-file>

```

Select **merge** to integrate changes into the base branch, then proceed with cleanup.

### Git Command Failures and Repository State Issues

**Symptom:** Raw Git errors like `git worktree add …` failing.

**Root Cause:** Repository is not a clean Git tree (detached HEAD, unresolved merge, missing `.git` directory).

**Diagnostic Steps:**

1. Run pre-flight checks manually:
   ```bash
   git rev-parse --is-inside-work-tree
   git worktree list
   ```

2. Check for detached HEAD:
   ```bash
   git symbolic-ref --short HEAD
   ```

**Resolution:**

- Resolve any Git conflicts and ensure you are on a valid branch.
- If the repository is corrupted, reclone it and reinitialize the worktree manager.
- Ensure the workflow's **pre_flight** block commands pass before invoking [`auto-worktree.yaml`](https://github.com/SynkraAI/aios-core/blob/main/auto-worktree.yaml).

### Stale Worktree Detection and Removal

**Symptom:** Dashboard shows outdated worktrees or [`status.json`](https://github.com/SynkraAI/aios-core/blob/main/status.json) contains invalid paths.

**Root Cause:** Worktrees exceed the `staleDays` threshold (default 30 days) or were manually deleted outside the manager.

**Diagnostic Steps:**

1. Inspect `manager.getCount()` to see stale counts.
2. Check [`.aios/status.json`](https://github.com/SynkraAI/aios-core/blob/main/.aios/status.json) for `activeWorktree` field accuracy.

**Resolution:**

Force clean stale worktrees:

```javascript
const WM = require('./.aios-core/infrastructure/scripts/worktree-manager');
const mgr = new WM(process.cwd());
const removed = await mgr.cleanupStale();
console.log('Cleaned up stale worktrees:', removed);

```

## Diagnostic Commands and Debugging Techniques

### Using the story-worktree-hooks.js CLI

The high-level CLI provides quick diagnostics without writing code:

```bash

# Check specific story status

node .aios-core/infrastructure/scripts/story-worktree-hooks.js status docs/stories/story-1.4.md

# List all worktrees

node .aios-core/infrastructure/scripts/story-worktree-hooks.js list

# Check effective configuration

node .aios-core/infrastructure/scripts/story-worktree-hooks.js config

```

### Programmatic Inspection with WorktreeManager

For deeper debugging, use the Node.js API directly:

```javascript
const WorktreeManager = require('./.aios-core/infrastructure/scripts/worktree-manager');

(async () => {
  const mgr = new WorktreeManager(process.cwd());
  
  // Get comprehensive counts
  const counts = await mgr.getCount();
  console.log(`Total: ${counts.total}, Active: ${counts.active}, Stale: ${counts.stale}`);
  
  // List all with metadata
  const worktrees = await mgr.list();
  console.log(worktrees);
  
  // Check specific worktree path
  const path = mgr.getWorktreePath('STORY-42');
  console.log('Worktree location:', path);
  
  // Detect merge conflicts before attempting merge
  const conflicts = await mgr.detectConflicts('STORY-42');
  if (conflicts.length) {
    console.warn('Conflicts detected:', conflicts);
  }
})();

```

### Enabling Verbose Logging

Set configuration flags to see detailed Git command execution:

```bash

# Environment variable

export AIOS_DEBUG=1

# Or set in auto-worktree.yaml

config:
  verbose: true

```

With verbose mode enabled, the manager prints chalk-colored logs for each `git worktree` command, making it easy to spot where failures occur.

## Code Examples for Troubleshooting

### Run the High-Level Hook from the CLI

```bash

# When a story moves to "In Progress"

node .aios-core/infrastructure/scripts/story-worktree-hooks.js start docs/stories/story-1.4.md

# When a story is marked "Done"

node .aios-core/infrastructure/scripts/story-worktree-hooks.js done docs/stories/story-1.4.md

```

Add `--force` to bypass a `manual` `autoCreate` setting, or `--keep-worktree` to prevent auto-cleanup.

### Detect Conflicts Before Merging a Story

```javascript
const WM = require('./.aios-core/infrastructure/scripts/worktree-manager');

(async () => {
  const mgr = new WM(process.cwd());
  const conflicts = await mgr.detectConflicts('STORY-42');
  if (conflicts.length) {
    console.warn('Conflicts would arise:', conflicts);
  } else {
    console.log('Safe to merge.');
  }
})();

```

### Force-Clean Stale Worktrees

```javascript
const WM = require('./.aios-core/infrastructure/scripts/worktree-manager');

(async () => {
  const mgr = new WM(process.cwd());
  const removed = await mgr.cleanupStale();   // returns array of storyIds removed
  console.log('Cleaned up stale worktrees:', removed);
})();

```

### Manually Merge a Worktree with Audit Log

```javascript
const WM = require('./.aios-core/infrastructure/scripts/worktree-manager');

(async () => {
  const mgr = new WM(process.cwd());
  const result = await mgr.mergeToBase('STORY-42', {
    squash: true,
    cleanup: true,
    message: 'Feature complete for STORY-42',
  });
  console.log('Merge result:', result);
})();

```

The `mergeToBase` method writes a JSON audit file under `.aios/logs/merges/`.

## Summary

- **Git worktree isolation** in aios-core relies on the `WorktreeManager` class in [`.aios-core/infrastructure/scripts/worktree-manager.js`](https://github.com/SynkraAI/aios-core/blob/main/.aios-core/infrastructure/scripts/worktree-manager.js), which wraps native Git commands and enforces limits via `maxWorktrees` (default 10) and `staleDays` (default 30).
- When troubleshooting, start with **CLI diagnostics** provided by [`story-worktree-hooks.js`](https://github.com/SynkraAI/aios-core/blob/main/story-worktree-hooks.js) (`status`, `list`, `config`) to quickly identify existing worktrees and configuration issues.
- For **"Worktree already exists"** errors, verify with `status` and use the `done` hook with cleanup options, or force-remove via the API with `manager.remove(storyId, {force: true})`.
- Resolve **maximum limit errors** by cleaning stale worktrees using `manager.cleanupStale()` or enabling `autoCleanup: true` in [`auto-worktree.yaml`](https://github.com/SynkraAI/aios-core/blob/main/auto-worktree.yaml).
- Address **uncommitted changes** by committing or stashing inside the worktree directory before invoking cleanup, or merge first using `mergeToBase()`.
- Use **verbose logging** (`AIOS_DEBUG=1` or `config.verbose: true`) and the Node.js REPL to inspect `getCount()`, `list()`, and `detectConflicts()` for deep debugging.

## Frequently Asked Questions

### How do I check if a story already has an active worktree?

Run the status command using the story file path:

```bash
node .aios-core/infrastructure/scripts/story-worktree-hooks.js status docs/stories/story-1.4.md

```

This returns JSON indicating `hasWorktree: true` or `false`, along with the filesystem path and uncommitted change count. You can also programmatically verify existence using `manager.getWorktreePath(storyId)` to check if the directory is registered in Git's worktree list.

### What is the default maximum number of worktrees allowed?

The default **maximum worktree limit is 10**, controlled by the `maxWorktrees` parameter in [`core-config.yaml`](https://github.com/SynkraAI/aios-core/blob/main/core-config.yaml) or [`auto-worktree.yaml`](https://github.com/SynkraAI/aios-core/blob/main/auto-worktree.yaml). When `manager.getCount().total` reaches this threshold, new worktree creation fails with a "Maximum worktrees limit reached" error. You can increase this limit in your configuration file or reduce the current count by removing stale worktrees via `manager.cleanupStale()`.

### How do I force remove a worktree that is marked as stale?

Use the `WorktreeManager` API with the `force` option to bypass safety checks:

```javascript
const WM = require('./.aios-core/infrastructure/scripts/worktree-manager');
const mgr = new WM(process.cwd());
await mgr.remove('STORY-42', {force: true});

```

Alternatively, run `cleanupStale()` to automatically remove all worktrees exceeding the `staleDays` threshold (default 30 days). For CLI-based removal, use `node story-worktree-hooks.js done <story-file>` followed by selecting the cleanup option, which handles both the Git worktree removal and directory cleanup.

### Why does the cleanup fail with uncommitted changes?

The `onStoryDone` hook and `cleanupStale()` methods check for uncommitted changes before removing a worktree to prevent accidental data loss. If `git status` detects modified or untracked files, the manager throws a "Worktree has X uncommitted changes" error and aborts the cleanup. To resolve this, navigate to the worktree directory (`.aios/worktrees/<storyId>`), commit or stash your changes, then retry the cleanup. Alternatively, use `mergeToBase()` first to integrate changes into the main branch before removing the worktree.