import { EventEmitter } from 'node:events';
import { n as nanoid } from '../shared/ccjk.BoApaI4j.mjs';
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
import { homedir } from 'node:os';
import { x as K } from './main.mjs';
import { j as join } from '../shared/ccjk.bQ7Dh1g4.mjs';
import { glob } from 'tinyglobby';
import { e as executionTracer } from '../shared/ccjk.DlTXS9rP.mjs';
import { f as fsParadigm } from '../shared/ccjk.wLJHO0Af.mjs';
import 'node:child_process';
import 'node:fs/promises';
import 'node:path';

class GitBackedStateManager extends EventEmitter {
  config;
  worktrees = /* @__PURE__ */ new Map();
  initialized = false;
  pendingCommits = /* @__PURE__ */ new Map();
  constructor(config = {}) {
    super();
    this.config = {
      workspaceRoot: config.workspaceRoot ?? join(homedir(), ".ccjk", "workspace"),
      useWorktrees: config.useWorktrees ?? true,
      autoCommit: config.autoCommit ?? true,
      compressionLevel: config.compressionLevel ?? 6,
      verbose: config.verbose ?? false,
      commitBatchInterval: config.commitBatchInterval ?? 1e3
    };
  }
  /**
   * Initialize the workspace with Git
   */
  async initialize() {
    if (this.initialized)
      return;
    const { workspaceRoot } = this.config;
    try {
      if (!existsSync(workspaceRoot)) {
        mkdirSync(workspaceRoot, { recursive: true });
        this.log(`Created workspace: ${workspaceRoot}`);
      }
      const gitDir = join(workspaceRoot, ".git");
      if (!existsSync(gitDir)) {
        await this.exec("git", ["init"], workspaceRoot);
        this.log("Initialized Git repository");
        const gitignore = `
# Sensitive data
*.env
*.key
*.pem
credentials.json

# Temporary files
*.tmp
*.log
*.swp

# OS files
.DS_Store
Thumbs.db
`;
        writeFileSync(join(workspaceRoot, ".gitignore"), gitignore.trim());
        await this.exec("git", ["add", ".gitignore"], workspaceRoot);
        await this.exec("git", ["commit", "-m", "Initial commit"], workspaceRoot);
        this.log("Created initial commit");
      }
      const agentsDir = join(workspaceRoot, "agents");
      if (!existsSync(agentsDir)) {
        mkdirSync(agentsDir, { recursive: true });
      }
      await this.loadExistingWorktrees();
      this.initialized = true;
      this.emit("initialized");
      this.log("GitBackedStateManager initialized");
    } catch (error) {
      const err = error instanceof Error ? error : new Error(String(error));
      this.emit("error", err);
      throw err;
    }
  }
  /**
   * Create isolated worktree for agent
   */
  async createAgentWorktree(agentId) {
    await this.ensureInitialized();
    const { workspaceRoot, useWorktrees } = this.config;
    if (this.worktrees.has(agentId)) {
      return this.worktrees.get(agentId);
    }
    const agentPath = join(workspaceRoot, "agents", agentId);
    if (useWorktrees) {
      const branchName = `agent/${agentId}`;
      try {
        await this.exec("git", ["checkout", "--orphan", branchName], workspaceRoot);
        await this.exec("git", ["reset", "--hard"], workspaceRoot);
        await this.exec("git", ["checkout", "main"], workspaceRoot).catch(() => {
          return this.exec("git", ["checkout", "master"], workspaceRoot);
        });
        if (!existsSync(agentPath)) {
          await this.exec("git", ["worktree", "add", agentPath, branchName], workspaceRoot);
        }
      } catch {
        if (!existsSync(agentPath)) {
          mkdirSync(agentPath, { recursive: true });
        }
      }
    } else {
      if (!existsSync(agentPath)) {
        mkdirSync(agentPath, { recursive: true });
      }
    }
    const stateFile = join(agentPath, "state.json");
    const mailboxFile = join(agentPath, "mailbox.json");
    if (!existsSync(stateFile)) {
      writeFileSync(stateFile, JSON.stringify({ agentId, createdAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
    }
    if (!existsSync(mailboxFile)) {
      writeFileSync(mailboxFile, JSON.stringify({ inbox: [], outbox: [], archive: [] }, null, 2));
    }
    this.worktrees.set(agentId, agentPath);
    this.emit("worktree:created", agentId, agentPath);
    this.log(`Created worktree for agent: ${agentId}`);
    return agentPath;
  }
  /**
   * Save agent state to Git
   */
  async saveState(agentId, state) {
    await this.ensureInitialized();
    const agentPath = await this.getOrCreateAgentPath(agentId);
    const stateFile = join(agentPath, "state.json");
    let existingState = {};
    if (existsSync(stateFile)) {
      try {
        existingState = JSON.parse(readFileSync(stateFile, "utf-8"));
      } catch {
      }
    }
    const newState = {
      ...existingState,
      ...state,
      updatedAt: (/* @__PURE__ */ new Date()).toISOString()
    };
    writeFileSync(stateFile, JSON.stringify(newState, null, 2));
    let commitId = "";
    if (this.config.autoCommit) {
      commitId = await this.batchCommit(agentId, `Update state: ${agentId}`);
    }
    this.emit("state:saved", agentId, commitId);
    this.log(`Saved state for agent: ${agentId}`);
    return commitId;
  }
  /**
   * Load agent state from Git
   */
  async loadState(agentId) {
    await this.ensureInitialized();
    const agentPath = this.worktrees.get(agentId);
    if (!agentPath) {
      return null;
    }
    const stateFile = join(agentPath, "state.json");
    if (!existsSync(stateFile)) {
      return null;
    }
    try {
      const state = JSON.parse(readFileSync(stateFile, "utf-8"));
      this.emit("state:loaded", agentId);
      this.log(`Loaded state for agent: ${agentId}`);
      return state;
    } catch {
      return null;
    }
  }
  /**
   * Rollback to previous state
   */
  async rollback(agentId, commitId) {
    await this.ensureInitialized();
    const agentPath = this.worktrees.get(agentId);
    if (!agentPath) {
      throw new Error(`Agent not found: ${agentId}`);
    }
    try {
      await this.exec("git", ["reset", "--hard", commitId], agentPath);
      this.emit("state:rolled-back", agentId, commitId);
      this.log(`Rolled back agent ${agentId} to commit ${commitId}`);
    } catch (error) {
      const err = error instanceof Error ? error : new Error(String(error));
      this.emit("error", err);
      throw err;
    }
  }
  /**
   * Get state history for agent
   */
  async getHistory(agentId, limit = 10) {
    await this.ensureInitialized();
    const agentPath = this.worktrees.get(agentId);
    if (!agentPath) {
      return [];
    }
    try {
      const result = await this.exec(
        "git",
        ["log", `--max-count=${limit}`, "--format=%H|%s|%ct", "--", "state.json"],
        agentPath
      );
      const snapshots = [];
      for (const line of result.stdout.split("\n").filter(Boolean)) {
        const [commitId, message, timestamp] = line.split("|");
        const stateResult = await this.exec(
          "git",
          ["show", `${commitId}:state.json`],
          agentPath
        ).catch(() => ({ stdout: "{}" }));
        let state;
        try {
          state = JSON.parse(stateResult.stdout);
        } catch {
          state = {};
        }
        snapshots.push({
          id: nanoid(),
          agentId,
          commitId,
          timestamp: Number.parseInt(timestamp, 10) * 1e3,
          message,
          state
        });
      }
      return snapshots;
    } catch {
      return [];
    }
  }
  /**
   * Cleanup agent worktree
   */
  async cleanup(agentId) {
    await this.ensureInitialized();
    const agentPath = this.worktrees.get(agentId);
    if (!agentPath) {
      return;
    }
    try {
      if (this.config.useWorktrees) {
        await this.exec("git", ["worktree", "remove", agentPath, "--force"], this.config.workspaceRoot);
      }
      this.worktrees.delete(agentId);
      this.emit("worktree:removed", agentId);
      this.log(`Cleaned up worktree for agent: ${agentId}`);
    } catch (error) {
      const err = error instanceof Error ? error : new Error(String(error));
      this.emit("error", err);
      throw err;
    }
  }
  /**
   * Get all agent IDs
   */
  getAgentIds() {
    return Array.from(this.worktrees.keys());
  }
  /**
   * Check if agent exists
   */
  hasAgent(agentId) {
    return this.worktrees.has(agentId);
  }
  /**
   * Get workspace root path
   */
  getWorkspaceRoot() {
    return this.config.workspaceRoot;
  }
  /**
   * Get agent path
   */
  getAgentPath(agentId) {
    return this.worktrees.get(agentId);
  }
  /**
   * Get state history for agent
   */
  async getStateHistory(agentId, limit = 20) {
    await this.ensureInitialized();
    const agentPath = this.worktrees.get(agentId);
    if (!agentPath) {
      return { agentId, commits: [], totalCommits: 0 };
    }
    try {
      const result = await this.exec(
        "git",
        ["log", `--max-count=${limit}`, "--format=%H|%s|%ct", "--", "state.json"],
        agentPath
      );
      const commits = result.stdout.split("\n").filter(Boolean).map((line) => {
        const [id, message, timestamp] = line.split("|");
        return {
          id,
          message,
          timestamp: Number.parseInt(timestamp, 10) * 1e3
        };
      });
      const countResult = await this.exec(
        "git",
        ["rev-list", "--count", "HEAD", "--", "state.json"],
        agentPath
      ).catch(() => ({ stdout: "0" }));
      return {
        agentId,
        commits,
        totalCommits: Number.parseInt(countResult.stdout.trim(), 10) || commits.length
      };
    } catch {
      return { agentId, commits: [], totalCommits: 0 };
    }
  }
  /**
   * Create a named snapshot of current state
   */
  async createSnapshot(agentId, description) {
    await this.ensureInitialized();
    const agentPath = this.worktrees.get(agentId);
    if (!agentPath) {
      throw new Error(`Agent not found: ${agentId}`);
    }
    const commitId = await this.commit(agentId, `Snapshot: ${description}`);
    if (!commitId) {
      const result = await this.exec("git", ["rev-parse", "HEAD"], agentPath);
      const currentCommitId = result.stdout.trim();
      const state2 = await this.loadState(agentId);
      return {
        id: nanoid(),
        agentId,
        commitId: currentCommitId,
        timestamp: Date.now(),
        message: description,
        state: state2 ?? {}
      };
    }
    const state = await this.loadState(agentId);
    return {
      id: nanoid(),
      agentId,
      commitId,
      timestamp: Date.now(),
      message: description,
      state: state ?? {}
    };
  }
  /**
   * Restore state from a snapshot
   */
  async restoreSnapshot(agentId, snapshotId) {
    await this.rollback(agentId, snapshotId);
  }
  /**
   * Sync with remote (if configured)
   */
  async syncWithRemote() {
    await this.ensureInitialized();
    try {
      const remoteResult = await this.exec("git", ["remote"], this.config.workspaceRoot);
      if (!remoteResult.stdout.trim()) {
        this.log("No remote configured, skipping sync");
        return;
      }
      await this.exec("git", ["pull", "--rebase"], this.config.workspaceRoot);
      await this.exec("git", ["push"], this.config.workspaceRoot);
      this.log("Synced with remote");
    } catch (error) {
      this.log(`Sync failed: ${error}`);
    }
  }
  // ========================================================================
  // Private Methods
  // ========================================================================
  async ensureInitialized() {
    if (!this.initialized) {
      await this.initialize();
    }
  }
  async getOrCreateAgentPath(agentId) {
    if (!this.worktrees.has(agentId)) {
      await this.createAgentWorktree(agentId);
    }
    return this.worktrees.get(agentId);
  }
  async loadExistingWorktrees() {
    const agentsDir = join(this.config.workspaceRoot, "agents");
    if (!existsSync(agentsDir)) {
      return;
    }
    try {
      const { readdirSync, statSync } = await import('node:fs');
      const entries = readdirSync(agentsDir);
      for (const entry of entries) {
        const entryPath = join(agentsDir, entry);
        if (statSync(entryPath).isDirectory()) {
          this.worktrees.set(entry, entryPath);
          this.log(`Loaded existing worktree: ${entry}`);
        }
      }
    } catch {
    }
  }
  async batchCommit(agentId, message) {
    const existing = this.pendingCommits.get(agentId);
    if (existing) {
      clearTimeout(existing);
    }
    return new Promise((resolve) => {
      const timeout = setTimeout(async () => {
        this.pendingCommits.delete(agentId);
        const commitId = await this.commit(agentId, message);
        resolve(commitId);
      }, this.config.commitBatchInterval);
      this.pendingCommits.set(agentId, timeout);
    });
  }
  async commit(agentId, message) {
    const agentPath = this.worktrees.get(agentId);
    if (!agentPath) {
      return "";
    }
    try {
      await this.exec("git", ["add", "-A"], agentPath);
      const statusResult = await this.exec("git", ["status", "--porcelain"], agentPath);
      if (!statusResult.stdout.trim()) {
        return "";
      }
      await this.exec("git", ["commit", "-m", message], agentPath);
      const result = await this.exec("git", ["rev-parse", "HEAD"], agentPath);
      return result.stdout.trim();
    } catch {
      return "";
    }
  }
  async exec(cmd, args, cwd) {
    const result = await K(cmd, args, { nodeOptions: { cwd } });
    return {
      stdout: result.stdout,
      stderr: result.stderr
    };
  }
  log(message) {
    if (this.config.verbose) {
      console.log(`[GitBackedState] ${message}`);
    }
  }
}
let globalStateManager = null;
function getGlobalStateManager(config) {
  if (!globalStateManager) {
    globalStateManager = new GitBackedStateManager(config);
  }
  return globalStateManager;
}

const gitBackedState = {
  __proto__: null,
  GitBackedStateManager: GitBackedStateManager,
  getGlobalStateManager: getGlobalStateManager
};

class ConvoyManager extends EventEmitter {
  stateManager;
  convoys = /* @__PURE__ */ new Map();
  initialized = false;
  constructor(stateManager) {
    super();
    this.stateManager = stateManager ?? getGlobalStateManager();
  }
  /**
   * Initialize convoy manager
   */
  async initialize() {
    if (this.initialized)
      return;
    await this.stateManager.initialize();
    await this.loadConvoys();
    this.initialized = true;
  }
  /**
   * Create new convoy
   */
  async create(name, options = {}) {
    await this.ensureInitialized();
    const convoy = {
      id: `cv-${nanoid(6)}`,
      name,
      description: options.description ?? "",
      tasks: [],
      status: "pending",
      progress: 0,
      totalTasks: 0,
      completedTasks: 0,
      failedTasks: 0,
      cancelledTasks: 0,
      skippedTasks: 0,
      createdAt: (/* @__PURE__ */ new Date()).toISOString(),
      createdBy: options.createdBy ?? "system",
      notifications: {
        onComplete: options.notifyOnComplete ?? false,
        onFailure: options.notifyOnFailure ?? true,
        onProgress: options.notifyOnProgress ?? false,
        notifyHuman: options.notifyHuman ?? false
      },
      metadata: options.metadata,
      tags: options.tags ?? []
    };
    this.convoys.set(convoy.id, convoy);
    await this.persistConvoy(convoy);
    this.emit("convoy:created", convoy);
    return convoy;
  }
  /**
   * Add task to convoy
   */
  async addTask(convoyId, title, options = {}) {
    await this.ensureInitialized();
    const convoy = this.convoys.get(convoyId);
    if (!convoy) {
      throw new Error(`Convoy not found: ${convoyId}`);
    }
    const task = {
      id: `task-${nanoid(6)}`,
      title,
      description: options.description ?? "",
      status: "pending",
      assignedTo: options.assignedTo,
      dependsOn: options.dependsOn ?? [],
      metadata: options.metadata
    };
    convoy.tasks.push(task);
    convoy.totalTasks = convoy.tasks.length;
    this.updateProgress(convoy);
    await this.persistConvoy(convoy);
    return task;
  }
  /**
   * Add multiple tasks to convoy
   */
  async addTasks(convoyId, tasks) {
    const addedTasks = [];
    for (const { title, options } of tasks) {
      const task = await this.addTask(convoyId, title, options);
      addedTasks.push(task);
    }
    return addedTasks;
  }
  /**
   * Start convoy execution
   */
  async start(convoyId) {
    await this.ensureInitialized();
    const convoy = this.convoys.get(convoyId);
    if (!convoy) {
      throw new Error(`Convoy not found: ${convoyId}`);
    }
    if (convoy.status !== "pending" && convoy.status !== "paused") {
      throw new Error(`Cannot start convoy in status: ${convoy.status}`);
    }
    convoy.status = "in_progress";
    convoy.startedAt = convoy.startedAt ?? (/* @__PURE__ */ new Date()).toISOString();
    await this.persistConvoy(convoy);
    this.emit("convoy:started", convoy);
  }
  /**
   * Start a task
   */
  async startTask(convoyId, taskId, assignedTo) {
    await this.ensureInitialized();
    const convoy = this.convoys.get(convoyId);
    if (!convoy) {
      throw new Error(`Convoy not found: ${convoyId}`);
    }
    const task = convoy.tasks.find((t) => t.id === taskId);
    if (!task) {
      throw new Error(`Task not found: ${taskId}`);
    }
    const unmetDeps = this.getUnmetDependencies(convoy, task);
    if (unmetDeps.length > 0) {
      throw new Error(`Task has unmet dependencies: ${unmetDeps.join(", ")}`);
    }
    task.status = "in_progress";
    task.startedAt = (/* @__PURE__ */ new Date()).toISOString();
    if (assignedTo) {
      task.assignedTo = assignedTo;
    }
    if (convoy.status === "pending") {
      convoy.status = "in_progress";
      convoy.startedAt = (/* @__PURE__ */ new Date()).toISOString();
    }
    await this.persistConvoy(convoy);
    this.emit("task:started", convoy, task);
  }
  /**
   * Complete a task
   */
  async completeTask(convoyId, taskId, result) {
    await this.ensureInitialized();
    const convoy = this.convoys.get(convoyId);
    if (!convoy) {
      throw new Error(`Convoy not found: ${convoyId}`);
    }
    const task = convoy.tasks.find((t) => t.id === taskId);
    if (!task) {
      throw new Error(`Task not found: ${taskId}`);
    }
    task.status = "completed";
    task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
    task.result = result;
    convoy.completedTasks++;
    this.updateProgress(convoy);
    this.checkConvoyCompletion(convoy);
    await this.persistConvoy(convoy);
    this.emit("task:completed", convoy, task);
    if (convoy.notifications.onProgress) {
      this.emit("convoy:progress", convoy, convoy.progress);
    }
  }
  /**
   * Fail a task
   */
  async failTask(convoyId, taskId, error) {
    await this.ensureInitialized();
    const convoy = this.convoys.get(convoyId);
    if (!convoy) {
      throw new Error(`Convoy not found: ${convoyId}`);
    }
    const task = convoy.tasks.find((t) => t.id === taskId);
    if (!task) {
      throw new Error(`Task not found: ${taskId}`);
    }
    task.status = "failed";
    task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
    task.error = error;
    convoy.failedTasks++;
    this.updateProgress(convoy);
    await this.skipDependentTasks(convoy, taskId);
    this.checkConvoyCompletion(convoy);
    await this.persistConvoy(convoy);
    this.emit("task:failed", convoy, task);
    if (convoy.notifications.onFailure) {
      this.emit("convoy:failed", convoy);
    }
  }
  /**
   * Cancel a task
   */
  async cancelTask(convoyId, taskId) {
    await this.ensureInitialized();
    const convoy = this.convoys.get(convoyId);
    if (!convoy) {
      throw new Error(`Convoy not found: ${convoyId}`);
    }
    const task = convoy.tasks.find((t) => t.id === taskId);
    if (!task) {
      throw new Error(`Task not found: ${taskId}`);
    }
    task.status = "cancelled";
    task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
    convoy.cancelledTasks++;
    this.updateProgress(convoy);
    await this.skipDependentTasks(convoy, taskId);
    this.checkConvoyCompletion(convoy);
    await this.persistConvoy(convoy);
    this.emit("task:cancelled", convoy, task);
  }
  /**
   * Pause convoy
   */
  async pause(convoyId) {
    await this.ensureInitialized();
    const convoy = this.convoys.get(convoyId);
    if (!convoy) {
      throw new Error(`Convoy not found: ${convoyId}`);
    }
    if (convoy.status !== "in_progress") {
      throw new Error(`Cannot pause convoy in status: ${convoy.status}`);
    }
    convoy.status = "paused";
    await this.persistConvoy(convoy);
    this.emit("convoy:paused", convoy);
  }
  /**
   * Resume convoy
   */
  async resume(convoyId) {
    await this.ensureInitialized();
    const convoy = this.convoys.get(convoyId);
    if (!convoy) {
      throw new Error(`Convoy not found: ${convoyId}`);
    }
    if (convoy.status !== "paused") {
      throw new Error(`Cannot resume convoy in status: ${convoy.status}`);
    }
    convoy.status = "in_progress";
    await this.persistConvoy(convoy);
    this.emit("convoy:resumed", convoy);
  }
  /**
   * Cancel convoy
   */
  async cancel(convoyId) {
    await this.ensureInitialized();
    const convoy = this.convoys.get(convoyId);
    if (!convoy) {
      throw new Error(`Convoy not found: ${convoyId}`);
    }
    convoy.status = "cancelled";
    convoy.completedAt = (/* @__PURE__ */ new Date()).toISOString();
    for (const task of convoy.tasks) {
      if (task.status === "pending" || task.status === "in_progress") {
        task.status = "cancelled";
        task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
        convoy.cancelledTasks++;
      }
    }
    this.updateProgress(convoy);
    await this.persistConvoy(convoy);
    this.emit("convoy:cancelled", convoy);
  }
  /**
   * Get convoy by ID
   */
  get(convoyId) {
    return this.convoys.get(convoyId);
  }
  /**
   * List all convoys
   */
  list(filter) {
    let convoys = Array.from(this.convoys.values());
    if (filter) {
      if (filter.status) {
        convoys = convoys.filter((c) => c.status === filter.status);
      }
      if (filter.createdBy) {
        convoys = convoys.filter((c) => c.createdBy === filter.createdBy);
      }
      if (filter.tags && filter.tags.length > 0) {
        convoys = convoys.filter(
          (c) => filter.tags.some((tag) => c.tags.includes(tag))
        );
      }
    }
    return convoys.sort(
      (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
    );
  }
  /**
   * Get active convoys
   */
  getActive() {
    return this.list({ status: "in_progress" });
  }
  /**
   * Get next available tasks (no unmet dependencies)
   */
  getNextTasks(convoyId) {
    const convoy = this.convoys.get(convoyId);
    if (!convoy)
      return [];
    return convoy.tasks.filter((task) => {
      if (task.status !== "pending")
        return false;
      return this.getUnmetDependencies(convoy, task).length === 0;
    });
  }
  /**
   * Get convoy summary
   */
  getSummary(convoyId) {
    const convoy = this.convoys.get(convoyId);
    if (!convoy)
      return "Convoy not found";
    const lines = [
      `Convoy: ${convoy.name} (${convoy.id})`,
      `Status: ${convoy.status}`,
      `Progress: ${convoy.progress}%`,
      `Tasks: ${convoy.completedTasks}/${convoy.totalTasks} completed`
    ];
    if (convoy.failedTasks > 0) {
      lines.push(`Failed: ${convoy.failedTasks}`);
    }
    if (convoy.cancelledTasks > 0) {
      lines.push(`Cancelled: ${convoy.cancelledTasks}`);
    }
    if (convoy.skippedTasks > 0) {
      lines.push(`Skipped: ${convoy.skippedTasks}`);
    }
    return lines.join("\n");
  }
  /**
   * Delete convoy
   */
  async delete(convoyId) {
    await this.ensureInitialized();
    const convoy = this.convoys.get(convoyId);
    if (!convoy)
      return false;
    this.convoys.delete(convoyId);
    return true;
  }
  // ========================================================================
  // Private Methods
  // ========================================================================
  async ensureInitialized() {
    if (!this.initialized) {
      await this.initialize();
    }
  }
  updateProgress(convoy) {
    const processed = convoy.completedTasks + convoy.failedTasks + convoy.cancelledTasks + convoy.skippedTasks;
    convoy.progress = convoy.totalTasks > 0 ? Math.round(processed / convoy.totalTasks * 100) : 0;
  }
  checkConvoyCompletion(convoy) {
    const processed = convoy.completedTasks + convoy.failedTasks + convoy.cancelledTasks + convoy.skippedTasks;
    if (processed === convoy.totalTasks) {
      convoy.completedAt = (/* @__PURE__ */ new Date()).toISOString();
      if (convoy.failedTasks === 0 && convoy.cancelledTasks === 0) {
        convoy.status = "completed";
        if (convoy.notifications.onComplete) {
          this.emit("convoy:completed", convoy);
        }
      } else {
        convoy.status = "failed";
        if (convoy.notifications.onFailure) {
          this.emit("convoy:failed", convoy);
        }
      }
    }
  }
  getUnmetDependencies(convoy, task) {
    return task.dependsOn.filter((depId) => {
      const depTask = convoy.tasks.find((t) => t.id === depId);
      return !depTask || depTask.status !== "completed";
    });
  }
  async skipDependentTasks(convoy, failedTaskId) {
    for (const task of convoy.tasks) {
      if (task.status === "pending" && task.dependsOn.includes(failedTaskId)) {
        task.status = "skipped";
        task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
        task.error = `Skipped due to failed dependency: ${failedTaskId}`;
        convoy.skippedTasks++;
        this.emit("task:skipped", convoy, task);
        await this.skipDependentTasks(convoy, task.id);
      }
    }
  }
  async loadConvoys() {
    for (const agentId of this.stateManager.getAgentIds()) {
      if (agentId.startsWith("convoy-")) {
        const state = await this.stateManager.loadState(agentId);
        if (state) {
          const convoy = state;
          this.convoys.set(convoy.id, convoy);
        }
      }
    }
  }
  async persistConvoy(convoy) {
    await this.stateManager.createAgentWorktree(`convoy-${convoy.id}`);
    await this.stateManager.saveState(`convoy-${convoy.id}`, convoy);
  }
}
let globalConvoyManager = null;
function getGlobalConvoyManager() {
  if (!globalConvoyManager) {
    globalConvoyManager = new ConvoyManager();
  }
  return globalConvoyManager;
}

const convoyManager = {
  __proto__: null,
  ConvoyManager: ConvoyManager,
  getGlobalConvoyManager: getGlobalConvoyManager
};

const DEPTH_TOKEN_BUDGETS = {
  L0: 100,
  // Abstract summary only
  L1: 2e3,
  // Overview
  L2: Number.POSITIVE_INFINITY
  // Full content
};
const PHASE_BUDGET_MULTIPLIERS = {
  exploring: 2,
  executing: 0.6,
  generating: 0.4,
  reviewing: 1.2,
  idle: 1
};
const CHARS_PER_TOKEN = 4;
function estimateTokens(text) {
  return Math.ceil(text.length / CHARS_PER_TOKEN);
}
function truncateToDepth(content, depth) {
  if (depth === "L2")
    return content;
  const maxChars = DEPTH_TOKEN_BUDGETS[depth] * CHARS_PER_TOKEN;
  if (content.length <= maxChars)
    return content;
  if (depth === "L0") {
    const firstPara = content.split(/\n\n/)[0];
    return firstPara.length <= maxChars ? firstPara : content.slice(0, maxChars);
  }
  return `${content.slice(0, maxChars)}
... (truncated, use L2 for full content)`;
}
class ContextLoader {
  cache = /* @__PURE__ */ new Map();
  defaultMaxSize = 1e5;
  // 100KB default
  defaultTokenBudget = 8e3;
  // ~32KB at 4 chars/token
  /**
   * Resolve effective depth from options.
   * If depth is explicit, use it. Otherwise derive from tokenBudget.
   */
  resolveDepth(tokenBudget, explicitDepth) {
    if (explicitDepth)
      return explicitDepth;
    if (tokenBudget <= DEPTH_TOKEN_BUDGETS.L0)
      return "L0";
    if (tokenBudget <= DEPTH_TOKEN_BUDGETS.L1)
      return "L1";
    return "L2";
  }
  /**
   * Load context hierarchically with OpenViking-style tiered depth control.
   * Pass tokenBudget to automatically select L0/L1/L2 depth.
   */
  async load(options = {}) {
    const {
      projectRoot = process.cwd(),
      maxSize = this.defaultMaxSize,
      tokenBudget,
      depth: explicitDepth,
      layers = ["project", "domain", "task", "execution"],
      task
    } = options;
    const phaseMultiplier = options.taskPhase ? PHASE_BUDGET_MULTIPLIERS[options.taskPhase] ?? 1 : 1;
    const effectiveBudget = Math.round((tokenBudget ?? this.defaultTokenBudget) * phaseMultiplier);
    const depth = this.resolveDepth(effectiveBudget, explicitDepth);
    const cacheKey = this.getCacheKey(projectRoot, layers, task?.id, depth);
    const cached = this.cache.get(cacheKey);
    if (cached && Date.now() - cached.loadedAt < 6e4) {
      executionTracer.logEvent("context-load", {
        source: "cache",
        layers: layers.length,
        size: cached.totalSize,
        tokens: cached.totalTokens,
        depth
      });
      return cached;
    }
    const context = {
      layers: /* @__PURE__ */ new Map(),
      totalSize: 0,
      totalTokens: 0,
      loadedAt: Date.now(),
      depth
    };
    for (const layer of layers) {
      const entries = await this.loadLayer(layer, projectRoot, task, depth);
      if (entries.length > 0) {
        context.layers.set(layer, entries);
        context.totalSize += entries.reduce((sum, e) => sum + e.content.length, 0);
        context.totalTokens += entries.reduce((sum, e) => sum + e.tokenEstimate, 0);
      }
      if (context.totalSize > maxSize || context.totalTokens > effectiveBudget) {
        break;
      }
    }
    this.cache.set(cacheKey, context);
    executionTracer.logEvent("context-load", {
      source: "fresh",
      layers: context.layers.size,
      size: context.totalSize,
      tokens: context.totalTokens,
      depth
    });
    return context;
  }
  /**
   * Load a specific context layer
   */
  async loadLayer(layer, projectRoot, task, depth = "L2") {
    switch (layer) {
      case "project":
        return this.loadProjectContext(projectRoot, depth);
      case "domain":
        return this.loadDomainContext(projectRoot, task, depth);
      case "task":
        return this.loadTaskContext(task, depth);
      case "execution":
        return this.loadExecutionContext(task, depth);
      default:
        return [];
    }
  }
  /**
   * Load project-level context
   * - README.md
   * - CLAUDE.md
   * - package.json
   * - tsconfig.json
   */
  async loadProjectContext(projectRoot, depth = "L2") {
    const entries = [];
    const files = ["README.md", "CLAUDE.md", "package.json", "tsconfig.json"];
    for (const file of files) {
      const path = join(projectRoot, file);
      if (existsSync(path)) {
        const raw = readFileSync(path, "utf-8");
        const content = truncateToDepth(raw, depth);
        entries.push({
          layer: "project",
          source: file,
          content,
          priority: 100,
          depth,
          tokenEstimate: estimateTokens(content),
          metadata: { path }
        });
      }
    }
    return entries;
  }
  /**
   * Load domain-specific context
   * Based on task type/domain, load relevant files
   */
  async loadDomainContext(projectRoot, task, depth = "L2") {
    if (!task)
      return [];
    const entries = [];
    const structure = await fsParadigm.detect(projectRoot);
    const domain = this.inferDomain(task);
    if (!domain) {
      const sourceFiles = fsParadigm.getFilesByRole(structure, "source");
      for (const file of sourceFiles.slice(0, 3)) {
        try {
          const raw = readFileSync(file, "utf-8");
          const content = truncateToDepth(raw, depth);
          entries.push({
            layer: "domain",
            source: file.replace(projectRoot, ""),
            content,
            priority: 75,
            depth,
            tokenEstimate: estimateTokens(content),
            metadata: { paradigm: structure.paradigm, path: file }
          });
        } catch {
        }
      }
      return entries;
    }
    const patterns = this.getDomainPatterns(domain, structure.paradigm);
    for (const pattern of patterns) {
      const files = await glob([pattern], {
        cwd: projectRoot,
        absolute: true,
        ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"]
      });
      for (const file of files.slice(0, 5)) {
        try {
          const raw = readFileSync(file, "utf-8");
          const content = truncateToDepth(raw, depth);
          entries.push({
            layer: "domain",
            source: file.replace(projectRoot, ""),
            content,
            priority: 80,
            depth,
            tokenEstimate: estimateTokens(content),
            metadata: { domain, paradigm: structure.paradigm, path: file }
          });
        } catch {
        }
      }
    }
    return entries;
  }
  /**
   * Load task-specific context
   */
  async loadTaskContext(task, depth = "L2") {
    if (!task)
      return [];
    const entries = [];
    if (task.description) {
      const content = truncateToDepth(task.description, depth);
      entries.push({
        layer: "task",
        source: "task-description",
        content,
        priority: 90,
        depth,
        tokenEstimate: estimateTokens(content),
        metadata: { taskId: task.id }
      });
    }
    if (task.input && depth !== "L0") {
      const content = truncateToDepth(JSON.stringify(task.input, null, 2), depth);
      entries.push({
        layer: "task",
        source: "task-input",
        content,
        priority: 85,
        depth,
        tokenEstimate: estimateTokens(content),
        metadata: { taskId: task.id }
      });
    }
    return entries;
  }
  /**
   * Load execution-specific context
   * - Recent errors
   * - Previous attempts
   * - Related task outputs
   */
  async loadExecutionContext(task, depth = "L2") {
    if (!task)
      return [];
    const entries = [];
    if (task.output && depth !== "L0") {
      const content = truncateToDepth(JSON.stringify(task.output, null, 2), depth);
      entries.push({
        layer: "execution",
        source: "previous-output",
        content,
        priority: 70,
        depth,
        tokenEstimate: estimateTokens(content),
        metadata: { taskId: task.id }
      });
    }
    return entries;
  }
  /**
   * Infer domain from task
   */
  inferDomain(task) {
    const text = `${task.name} ${task.description || ""}`.toLowerCase();
    const domains = {
      api: ["api", "endpoint", "route", "controller"],
      ui: ["ui", "component", "view", "page", "frontend"],
      database: ["database", "db", "schema", "migration", "model"],
      auth: ["auth", "login", "user", "permission", "session"],
      test: ["test", "spec", "e2e", "unit", "integration"],
      config: ["config", "settings", "env", "setup"]
    };
    for (const [domain, keywords] of Object.entries(domains)) {
      if (keywords.some((kw) => text.includes(kw))) {
        return domain;
      }
    }
    return null;
  }
  /**
   * Get file patterns for a domain (paradigm-aware)
   */
  getDomainPatterns(domain, paradigm) {
    const basePatterns = {
      api: ["**/api/**/*.ts", "**/routes/**/*.ts", "**/controllers/**/*.ts"],
      ui: ["**/components/**/*.{tsx,vue}", "**/pages/**/*.{tsx,vue}", "**/views/**/*.{tsx,vue}"],
      database: ["**/models/**/*.ts", "**/schema/**/*.ts", "**/migrations/**/*.ts"],
      auth: ["**/auth/**/*.ts", "**/middleware/auth*.ts"],
      test: ["**/*.test.ts", "**/*.spec.ts"],
      config: ["**/config/**/*.ts", "**/*.config.ts"]
    };
    let patterns = basePatterns[domain] || [];
    if (paradigm === "monorepo") {
      patterns = patterns.map((p) => `packages/*/${p}`);
    } else if (paradigm === "fullstack") {
      if (domain === "ui") {
        patterns = patterns.map((p) => `client/${p}`);
      } else if (domain === "api") {
        patterns = patterns.map((p) => `server/${p}`);
      }
    }
    return patterns;
  }
  /**
   * Get cache key
   */
  getCacheKey(projectRoot, layers, taskId, depth = "L2") {
    return `${projectRoot}:${layers.join(",")}:${taskId || "none"}:${depth}`;
  }
  /**
   * Clear cache
   */
  clearCache() {
    this.cache.clear();
  }
  /**
   * Format context for LLM consumption
   */
  formatForLLM(context) {
    const sections = [];
    sections.push(`<!-- context depth=${context.depth} tokens\u2248${context.totalTokens} -->
`);
    const layerOrder = ["project", "domain", "task", "execution"];
    for (const layer of layerOrder) {
      const entries = context.layers.get(layer);
      if (!entries || entries.length === 0)
        continue;
      sections.push(`# ${layer.toUpperCase()} CONTEXT
`);
      const sorted = entries.sort((a, b) => b.priority - a.priority);
      for (const entry of sorted) {
        sections.push(`## ${entry.source} [${entry.depth}]
`);
        sections.push(entry.content);
        sections.push("\n");
      }
    }
    return sections.join("\n");
  }
}
const contextLoader = new ContextLoader();
async function loadContextAtDepth(depth, options = {}) {
  return contextLoader.load({ ...options, depth });
}

const contextLoader$1 = {
  __proto__: null,
  ContextLoader: ContextLoader,
  contextLoader: contextLoader,
  loadContextAtDepth: loadContextAtDepth
};

function detectTaskPhase(history) {
  if (history.length === 0)
    return "idle";
  const recent = history.slice(-10);
  const recentText = recent.map((h) => h.content).join(" ").toLowerCase();
  if (recentText.includes("write") || recentText.includes("create") || recentText.includes("generating"))
    return "generating";
  if (recentText.includes("test") || recentText.includes("review") || recentText.includes("check"))
    return "reviewing";
  if (recentText.includes("edit") || recentText.includes("bash") || recentText.includes("run"))
    return "executing";
  if (recentText.includes("read") || recentText.includes("search") || recentText.includes("grep"))
    return "exploring";
  return "idle";
}
function extractFilePaths(content) {
  const matches = content.match(/\/[\w./\-]+\.\w+|[\w./\-]+\.(?:ts|js|json|md|py|go|rs)/g);
  return matches ? [...new Set(matches)] : [];
}
class SessionIntelligence {
  static instance = null;
  session;
  constructor(session) {
    this.session = session;
    if (!session.intelligence) {
      session.intelligence = {
        taskPhase: "idle",
        filesTouched: [],
        keyDecisions: [],
        toolCallCount: 0,
        compressionWatermark: 0
      };
    }
  }
  get state() {
    return this.session.intelligence;
  }
  /**
   * Observe a new history entry and update intelligence state.
   * Call this after every message added to the session.
   */
  observe(entry) {
    const intel = this.state;
    if (!intel.userOriginalIntent && entry.role === "user" && entry.content.trim().length > 10) {
      intel.userOriginalIntent = entry.content.slice(0, 500);
    }
    const files = extractFilePaths(entry.content);
    for (const f of files) {
      if (!intel.filesTouched.includes(f)) {
        intel.filesTouched.push(f);
      }
    }
    if (entry.role === "assistant" && /\b(bash|read|write|edit|grep|glob)\b/i.test(entry.content)) {
      intel.toolCallCount++;
    }
    intel.taskPhase = detectTaskPhase(this.session.history);
  }
  /**
   * Record a key decision explicitly.
   */
  recordDecision(decision) {
    const intel = this.state;
    if (!intel.keyDecisions.includes(decision)) {
      intel.keyDecisions.push(decision.slice(0, 200));
      if (intel.keyDecisions.length > 20) {
        intel.keyDecisions.shift();
      }
    }
  }
  /**
   * Mark that history up to index N has been compressed.
   */
  markCompressed(upToIndex) {
    this.state.compressionWatermark = upToIndex;
  }
  /**
   * Generate a system prompt injection that preserves intent across compaction.
   * Inject this whenever context is about to be compressed.
   */
  getSystemPromptInjection() {
    const intel = this.state;
    const parts = ["<!-- session-intelligence -->"];
    if (intel.userOriginalIntent) {
      parts.push(`Original user intent: ${intel.userOriginalIntent}`);
    }
    if (intel.keyDecisions.length > 0) {
      parts.push(`Key decisions: ${intel.keyDecisions.join("; ")}`);
    }
    if (intel.filesTouched.length > 0) {
      parts.push(`Files touched: ${intel.filesTouched.slice(-20).join(", ")}`);
    }
    parts.push(`Task phase: ${intel.taskPhase} | Tool calls: ${intel.toolCallCount}`);
    parts.push("<!-- /session-intelligence -->");
    return parts.join("\n");
  }
  /**
   * Returns true if the session has enough context to be worth preserving.
   */
  hasSignificantContext() {
    const intel = this.state;
    return !!intel.userOriginalIntent || intel.toolCallCount > 3 || intel.filesTouched.length > 0;
  }
  static getInstance() {
    if (!SessionIntelligence.instance) {
      SessionIntelligence.instance = new SessionIntelligence({
        id: "session-intelligence-singleton",
        createdAt: /* @__PURE__ */ new Date(),
        lastUsedAt: /* @__PURE__ */ new Date(),
        history: []
      });
    }
    return SessionIntelligence.instance;
  }
  recordMessage(role, content) {
    const entry = {
      timestamp: /* @__PURE__ */ new Date(),
      role,
      content
    };
    this.session.history.push(entry);
    this.observe(entry);
  }
  updatePhase(phase) {
    this.state.taskPhase = phase;
  }
}

export { SessionIntelligence as S, getGlobalStateManager as a, gitBackedState as b, contextLoader as c, convoyManager as d, contextLoader$1 as e, getGlobalConvoyManager as g };
