# Migration Guide: Hash-Based Architecture **Date**: 2026-02-17 **Breaking Change**: Yes **Affects**: All users with existing sessions ## What Changed Agent Orchestrator has migrated from flat, configurable directories (`dataDir` and `worktreeDir`) to a **hash-based project isolation** architecture. This change eliminates configuration overhead and prevents collisions when running multiple orchestrator instances from different directories. ### Before (Flat Architecture) ```yaml # agent-orchestrator.yaml dataDir: ~/.ao-sessions worktreeDir: ~/.ao-worktrees projects: my-app: path: ~/repos/my-app ``` **Problems**: - Multiple configs sharing same `dataDir` caused session collisions - Manual path configuration required - No isolation between orchestrator instances - Backwards compatibility code added complexity ### After (Hash-Based Architecture) ```yaml # agent-orchestrator.yaml # No dataDir or worktreeDir needed! projects: my-app: path: ~/repos/my-app ``` **Benefits**: - Zero configuration — paths auto-derived from config location - Complete isolation — each config gets unique namespace - Collision-free — SHA256 hash prevents conflicts - Clean codebase — no backwards compatibility code ## Architecture Details ### Directory Structure All orchestrator data now lives under `~/.agent-orchestrator/`: ``` ~/.agent-orchestrator/ ├── {hash}-{projectId}/ # Unique per config+project │ ├── .origin # Stores config path (collision detection) │ ├── sessions/ # Session metadata │ │ ├── int-1 # Metadata for session int-1 │ │ ├── int-2 │ │ └── archive/ # Archived metadata │ └── worktrees/ # Git worktrees │ ├── int-1/ # Worktree for session int-1 │ └── int-2/ ``` ### Hash Generation The hash is the first 12 characters of `SHA256(realpath(dirname(configPath)))`: ```typescript // Config at: ~/projects/acme/agent-orchestrator.yaml // Hash of: /Users/you/projects/acme // Result: a3b4c5d6e7f8 // Final path: ~/.agent-orchestrator/a3b4c5d6e7f8-my-app/ ``` **Why 12 chars?** Balance between uniqueness (collision probability ~1 in 16 billion) and path length. ### Session Naming Layers Three levels of naming for compatibility: 1. **User-facing**: `int-1`, `ao-42` (short, clean) 2. **Tmux**: `a3b4c5d6e7f8-int-1` (globally unique across all configs) 3. **Metadata file**: `int-1` (within project-specific `sessions/` directory) ## Breaking Changes ### 1. Config File Changes **REMOVED fields** (will cause validation errors if present): - `dataDir` - `worktreeDir` **REQUIRED field**: - `configPath` (automatically set by `loadConfig()`) **Migration**: ```diff # agent-orchestrator.yaml - dataDir: ~/.ao-sessions - worktreeDir: ~/.ao-worktrees projects: my-app: path: ~/repos/my-app ``` ### 2. Metadata File Locations **Before**: ``` ~/.ao-sessions/ ├── int-1 # Flat directory, all projects mixed ├── int-2 ├── ao-1 └── ao-2 ``` **After**: ``` ~/.agent-orchestrator/ ├── a3b4c5d6e7f8-integrator/sessions/ │ ├── int-1 # Integrator project sessions │ └── int-2 └── f9e8d7c6b5a4-my-app/sessions/ ├── ao-1 # My-app project sessions └── ao-2 ``` **Impact**: Existing metadata files **will not be automatically migrated**. See migration steps below. ### 3. Worktree Locations **Before**: ``` ~/.ao-worktrees/ ├── integrator/ │ ├── int-1 │ └── int-2 └── my-app/ ├── ao-1 └── ao-2 ``` **After**: ``` ~/.agent-orchestrator/ ├── a3b4c5d6e7f8-integrator/worktrees/ │ ├── int-1 │ └── int-2 └── f9e8d7c6b5a4-my-app/worktrees/ ├── ao-1 └── ao-2 ``` **Impact**: Existing worktrees **will not be automatically migrated**. Git will report them as "missing" and they must be manually removed. ### 4. Environment Variables **Before**: ```bash AO_DATA_DIR=~/.ao-sessions # Flat path ``` **After**: ```bash AO_DATA_DIR=~/.agent-orchestrator/a3b4c5d6e7f8-integrator/sessions/ ``` **Impact**: Scripts or hooks relying on `AO_DATA_DIR` pointing to a flat directory will break. ### 5. API Changes (For Plugin Developers) **Removed from `OrchestratorConfig`**: ```typescript interface OrchestratorConfig { dataDir: string; // REMOVED worktreeDir: string; // REMOVED configPath: string; // NOW REQUIRED } ``` **New Path Utilities** (use these instead): ```typescript import { getSessionsDir, getWorktreesDir, getProjectBaseDir, generateConfigHash, generateInstanceId, validateAndStoreOrigin, } from "@composio/ao-core"; // Calculate paths dynamically const sessionsDir = getSessionsDir(configPath, projectPath); const worktreesDir = getWorktreesDir(configPath, projectPath); ``` ## Migration Steps ### Step 1: Clean Up Config File Remove `dataDir` and `worktreeDir` from your config: ```bash # Edit your agent-orchestrator.yaml vim ~/path/to/agent-orchestrator.yaml ``` Remove these lines: ```yaml dataDir: ~/.ao-sessions worktreeDir: ~/.ao-worktrees ``` ### Step 2: Kill Existing Sessions **IMPORTANT**: Existing sessions will **not** automatically migrate. You must kill them first. ```bash # List all tmux sessions tmux ls # Kill all orchestrator sessions (adjust prefix as needed) tmux ls | grep -E '^(int|ao|app)-[0-9]+:' | cut -d: -f1 | xargs -I{} tmux kill-session -t {} # Or kill all tmux sessions (nuclear option) tmux kill-server ``` ### Step 3: Clean Up Old Directories **Worktrees** must be removed from git: ```bash # For each project, remove old worktrees cd ~/repos/integrator # List worktrees git worktree list # Remove each old worktree git worktree remove ~/.ao-worktrees/integrator/int-1 --force git worktree remove ~/.ao-worktrees/integrator/int-2 --force # ... repeat for all # Prune stale references git worktree prune ``` **Metadata** can be archived for reference: ```bash # Archive old metadata (optional) mv ~/.ao-sessions ~/.ao-sessions-backup-$(date +%Y%m%d) # Or delete if you don't need it rm -rf ~/.ao-sessions ``` **Worktree directory** can be removed after cleaning up git references: ```bash # Remove old worktree directory (after git worktree remove) rm -rf ~/.ao-worktrees ``` ### Step 4: Update to Latest Version ```bash # Pull latest code git pull origin main # Reinstall dependencies pnpm install # Rebuild packages pnpm build ``` ### Step 5: Start Fresh ```bash # Start orchestrator (creates new directory structure) ao start # Spawn new sessions (uses hash-based paths) ao spawn my-app INT-1234 ``` ### Step 6: Verify New Structure ```bash # Check that new directories were created ls -la ~/.agent-orchestrator/ # You should see directories like: # a3b4c5d6e7f8-my-app/ # .origin # sessions/ # worktrees/ # Check tmux sessions have hash prefix tmux ls # Should show: a3b4c5d6e7f8-int-1, a3b4c5d6e7f8-int-2, etc. ``` ## Rollback (If Needed) If you need to rollback to the old architecture: 1. **Checkout previous commit** (before hash-based migration): ```bash git checkout pnpm install pnpm build ``` 2. **Restore old config**: ```bash # Add back to agent-orchestrator.yaml dataDir: ~/.ao-sessions worktreeDir: ~/.ao-worktrees ``` 3. **Restore old metadata** (if archived): ```bash mv ~/.ao-sessions-backup-20260217 ~/.ao-sessions ``` 4. **Kill new hash-based sessions**: ```bash tmux ls | grep -E '^[a-f0-9]{12}-' | cut -d: -f1 | xargs -I{} tmux kill-session -t {} ``` ## FAQ ### Q: Why can't I use my old sessions? **A**: The metadata file structure changed. Old sessions point to flat directories (`~/.ao-sessions/int-1`) but the new code expects hash-based paths (`~/.agent-orchestrator/a3b4c5d6e7f8-integrator/sessions/int-1`). You must kill old sessions and spawn new ones. ### Q: Will my PRs be lost? **A**: No! PRs are on GitHub, not in local sessions. You can: 1. Check `gh pr list` to see all open PRs 2. Spawn new sessions for PRs that need work: `ao spawn integrator --branch feat/existing-branch` ### Q: What about in-progress work? **A**: Git worktrees contain your code changes. Before killing sessions: 1. Commit or stash changes in each worktree 2. Note which issues/branches were being worked on 3. After migration, spawn new sessions and continue work ### Q: Can I migrate metadata files manually? **A**: Yes, but **not recommended**. The manual process: ```bash # For each project OLD_DIR=~/.ao-sessions NEW_DIR=~/.agent-orchestrator/$(python3 -c "import hashlib; print(hashlib.sha256(b'/Users/you/path/to/config/dir').hexdigest()[:12])")-integrator/sessions mkdir -p "$NEW_DIR" # Copy metadata files cp "$OLD_DIR"/int-* "$NEW_DIR/" # Update worktree paths in each file (required!) for file in "$NEW_DIR"/*; do sed -i '' 's|worktree=~/.ao-worktrees/integrator/|worktree=~/.agent-orchestrator/HASH-integrator/worktrees/|g' "$file" done ``` This is error-prone. **Recommended**: Kill old sessions and spawn fresh ones. ### Q: What happens if I have multiple config files? **A**: Each config gets a unique hash! This is the **main benefit** of the new architecture: ```bash # Config 1: ~/projects/acme/agent-orchestrator.yaml # Hash: a3b4c5d6e7f8 # Sessions: ~/.agent-orchestrator/a3b4c5d6e7f8-my-app/ # Config 2: ~/experiments/test/agent-orchestrator.yaml # Hash: 1f2e3d4c5b6a # Sessions: ~/.agent-orchestrator/1f2e3d4c5b6a-my-app/ ``` No conflicts, complete isolation! ### Q: How do I find the hash for my config? **A**: ```bash # Calculate hash for your config directory echo -n "/path/to/your/config/dir" | sha256sum | cut -c1-12 # Or let ao print it ao status # Output shows: Config: /path/to/config.yaml # Hash will be in directory names: ~/.agent-orchestrator/{hash}-{project}/ ``` ### Q: What if two configs have the same hash (collision)? **A**: The `.origin` file detects this and throws an error with instructions: ``` Hash collision detected! Directory: ~/.agent-orchestrator/a3b4c5d6e7f8-my-app Expected config: /Users/you/config1/agent-orchestrator.yaml Actual config: /Users/you/config2/agent-orchestrator.yaml This is a rare hash collision. Please move one of the configs to a different directory. ``` **Solution**: Move one config to a different directory. Collision probability is ~1 in 16 billion with 12-character hashes. ## Support If you encounter issues during migration: 1. Check existing sessions: `tmux ls` 2. Check new directory structure: `ls -la ~/.agent-orchestrator/` 3. Check config validation: `ao status` 4. Review git worktrees: `git worktree list` (from project directory) 5. Check logs: `journalctl -u ao-orchestrator` or tmux session output For bugs or questions, file an issue: https://github.com/composiohq/agent-orchestrator/issues ## Summary **Action Required**: 1. ✅ Remove `dataDir` and `worktreeDir` from config 2. ✅ Kill all existing sessions (`tmux kill-server`) 3. ✅ Clean up old git worktrees (`git worktree remove --force`) 4. ✅ Remove old directories (`~/.ao-sessions`, `~/.ao-worktrees`) 5. ✅ Update to latest version (`pnpm install && pnpm build`) 6. ✅ Start fresh (`ao start`, `ao spawn`) **Expected Downtime**: ~10 minutes (time to kill sessions, clean worktrees, respawn) **Risk Level**: Low (PRs are safe, code is in git, only local sessions affected) **Benefit**: Cleaner architecture, zero config, collision-free multi-instance support