Skip to content

Latest commit

 

History

History
309 lines (230 loc) · 6.88 KB

File metadata and controls

309 lines (230 loc) · 6.88 KB

Final Architecture Plan

Core Principles

  1. Convention over configuration - Auto-derive everything possible
  2. Single source of truth - Config file in repo, runtime data in ~/.agent-orchestrator/
  3. Zero path configuration - All paths determined automatically
  4. Global uniqueness - Hash-based namespacing prevents collisions

1. Directory Structure

Repo (versioned):
~/any/path/to/agent-orchestrator/
  agent-orchestrator.yaml              ← Config file (only this matters)
  packages/
  ...

Runtime Data (not versioned):
~/.agent-orchestrator/                 ← Single parent directory
  a3b4c5d6e7f8-integrator/             ← {hash}-{projectId}
    sessions/
      int-1                            ← Session metadata files (no hash prefix)
      int-2
    worktrees/
      int-1/                           ← Git worktrees (no hash prefix)
      int-2/
    archive/
      int-3_2026-02-17T10-30-00
    .origin                            ← Config path reference

  a3b4c5d6e7f8-backend/                ← Same hash (same config!)
    sessions/
      be-1                             ← No hash prefix (already namespaced)
    worktrees/
      be-1/
    .origin

Hash Derivation (from config location):

const configDir = path.dirname(configPath); // /Users/alice/code/agent-orchestrator
const hash = sha256(configDir).slice(0, 12); // a3b4c5d6e7f8

// Each project managed by this config gets a directory
// Format: {hash}-{projectId}
const projectId = path.basename(projectPath); // integrator, backend, etc.
const instanceId = `${hash}-${projectId}`; // a3b4c5d6e7f8-integrator

// Not configurable!
const projectBaseDir = `~/.agent-orchestrator/${instanceId}`;
const sessionsDir = `${projectBaseDir}/sessions`;
const worktreesDir = `${projectBaseDir}/worktrees`;

Key insight: All projects from the same config share the same hash prefix!


2. Config File (Minimal)

# agent-orchestrator.yaml

projects:
  - path: ~/repos/integrator # Required: where is the repo?
    repo: ComposioHQ/integrator # Required: GitHub repo
    defaultBranch: next # Required: base branch

    # Optional overrides:
    name: Composio Integrator # Display name (default: folder name)
    sessionPrefix: int # Override auto-generated prefix

Auto-derived:

  • Project ID: basename(path)integrator
  • Session prefix: generatePrefix("integrator")int
  • Worktree path: {worktreeDir}/integrator/

That's it! No dataDir, no worktreeDir, no explicit IDs.


3. Session Naming

User-Facing Names (Elegant)

{sessionPrefix}-{num}

int-1, int-2    (integrator)
ao-1, ao-2      (agent-orchestrator)
ss-1, ss-2      (safe-split)

Tmux Session Names (Globally Unique)

{hash}-{sessionPrefix}-{num}

a3b4c5d6e7f8-int-1
a3b4c5d6e7f8-ao-1
f1e2d3c4b5a6-int-1    (different checkout, no collision!)

Prefix Generation (Clean Heuristic)

function generateSessionPrefix(projectId: string): string {
  if (projectId.length <= 4) return projectId.toLowerCase();

  // CamelCase: PyTorch → pt
  const uppercase = projectId.match(/[A-Z]/g);
  if (uppercase?.length > 1) {
    return uppercase.join("").toLowerCase();
  }

  // kebab-case: agent-orchestrator → ao
  if (projectId.includes("-") || projectId.includes("_")) {
    const sep = projectId.includes("-") ? "-" : "_";
    return projectId
      .split(sep)
      .map((w) => w[0])
      .join("")
      .toLowerCase();
  }

  // Single word: integrator → int
  return projectId.slice(0, 3).toLowerCase();
}

4. Metadata Storage

File Structure (One Directory Per Project)

~/.agent-orchestrator/a3b4c5d6e7f8-integrator/
  sessions/
    int-1      ← Metadata file (user-facing session name)
    int-2
  worktrees/
    int-1/
    int-2/
  archive/
    int-3_2026-02-17T10-30-00

Metadata File Format (key=value)

project=integrator
issue=INT-100
branch=feat/INT-100
status=working
tmuxName=a3b4c5d6e7f8-int-1
worktree=/Users/alice/.agent-orchestrator/a3b4c5d6e7f8-integrator/worktrees/int-1
createdAt=2026-02-17T10:30:00Z
pr=https://github.com/ComposioHQ/integrator/pull/123

Key fields:

  • project - Which project this session belongs to (for filtering)
  • issue - Linear/GitHub issue ID
  • branch - Git branch name
  • worktree - Path to git worktree
  • status - working/idle/pr_open/merged

5. User Commands (Simple)

# List all sessions
ao list

# List sessions for specific project
ao list integrator

# Spawn new session
ao spawn integrator INT-100

# Attach to session (orchestrator finds tmux name)
ao attach int-1

# Kill session
ao kill int-1

# Show instance info
ao info

No config paths in commands! Everything auto-discovered.


6. Multi-Instance Support

Same Config → Same Hash

# ~/code/my-orchestrator/agent-orchestrator.yaml
projects:
  - path: ~/repos/integrator
  - path: ~/repos/backend

Results in:

~/.agent-orchestrator/
  a3b4c5d6e7f8-integrator/        ← Same hash (same config)
  a3b4c5d6e7f8-backend/           ← Same hash (same config)

Different Config Locations → Different Hashes

~/code/orchestrator/              → hash: a3b4c5d6e7f8
~/code/orchestrator-v2/           → hash: f1e2d3c4b5a6
~/splitly-orchestrator/           → hash: 9876abcd5432

Results in:

~/.agent-orchestrator/
  a3b4c5d6e7f8-integrator/        ← From ~/code/orchestrator
  f1e2d3c4b5a6-integrator/        ← From ~/code/orchestrator-v2 (different checkout!)
  9876abcd5432-safesplit/         ← From ~/splitly-orchestrator

# Sessions (no collisions):
a3b4c5d6e7f8-int-1    (main checkout)
f1e2d3c4b5a6-int-1    (v2 checkout)
9876abcd5432-ss-1     (splitly)

Each orchestrator checkout gets unique hash. Projects within same config share that hash.


7. Complete Example

# ~/code/my-orchestrator/agent-orchestrator.yaml
projects:
  - path: ~/repos/integrator
    repo: ComposioHQ/integrator
    defaultBranch: next

  - path: ~/repos/backend
    repo: ComposioHQ/backend
    defaultBranch: main
    sessionPrefix: be # Override auto-generated "bac"

Results in:

Config location:
  ~/code/my-orchestrator/
  → Hash: a3b4c5d6e7f8

Runtime data:
  ~/.agent-orchestrator/
    a3b4c5d6e7f8-integrator/      ← Project 1
      sessions/
        int-1
      worktrees/
        int-1/

    a3b4c5d6e7f8-backend/         ← Project 2 (same hash!)
      sessions/
        be-1
      worktrees/
        be-1/

Session names:
  User-facing: int-1, be-1
  Tmux: a3b4c5d6e7f8-int-1, a3b4c5d6e7f8-be-1

Commands:
  ao spawn integrator INT-100
  ao attach int-1

Summary: What Users Configure

Required (3 fields per project):

  1. path - Where is the repo?
  2. repo - GitHub owner/repo
  3. defaultBranch - Base branch name

Optional:

  • sessionPrefix - Override auto-generated prefix
  • name - Display name

That's it! Everything else is automatic.