#!/usr/bin/env node
process.env["STACKMEMORY_CLI"] = "true";
import { program } from "commander";
import { logger } from "../core/monitoring/logger.js";
import { FrameManager } from "../core/context/frame-manager.js";
import { sessionManager, FrameQueryMode } from "../core/session/index.js";
import { sharedContextLayer } from "../core/context/shared-context-layer.js";
import { LinearTaskManager } from "../features/tasks/linear-task-manager.js";
import {
  LinearAuthManager,
  LinearOAuthSetup
} from "../integrations/linear/auth.js";
import {
  LinearSyncEngine,
  DEFAULT_SYNC_CONFIG
} from "../integrations/linear/sync.js";
import {
  initializeAutoSync,
  getAutoSyncService,
  stopAutoSync
} from "../integrations/linear/auto-sync.js";
import { LinearConfigManager } from "../integrations/linear/config.js";
import { UpdateChecker } from "../core/utils/update-checker.js";
import { ProgressTracker } from "../core/monitoring/progress-tracker.js";
import { registerProjectCommands } from "./commands/projects.js";
import { registerLinearCommands } from "./commands/linear.js";
import { registerLinearTestCommand } from "./commands/linear-test.js";
import { registerLinearListCommand } from "./commands/linear-list.js";
import { registerLinearMigrateCommand } from "./commands/linear-migrate.js";
import { registerLinearCreateCommand } from "./commands/linear-create.js";
import { createChromaDBCommand } from "./commands/chromadb.js";
import { createInfiniteStorageCommand } from "./commands/infinite-storage.js";
import { createGCCommand } from "./commands/gc.js";
import { createSessionCommands } from "./commands/session.js";
import { registerWorktreeCommands } from "./commands/worktree.js";
import { registerOnboardingCommand } from "./commands/onboard.js";
import { webhookCommand } from "./commands/webhook.js";
import { createTaskCommands } from "./commands/tasks.js";
import { createSearchCommand } from "./commands/search.js";
import { createLogCommand } from "./commands/log.js";
import { createContextCommands } from "./commands/context.js";
import { createConfigCommand } from "./commands/config.js";
import { createAgentCommand } from "./commands/agent.js";
import { createHandoffCommand } from "./commands/handoff.js";
import { createStorageCommand } from "./commands/storage.js";
import { createSkillsCommand } from "./commands/skills.js";
import { createTestCommand } from "./commands/test.js";
import clearCommand from "./commands/clear.js";
import createWorkflowCommand from "./commands/workflow.js";
import monitorCommand from "./commands/monitor.js";
import qualityCommand from "./commands/quality.js";
import { ProjectManager } from "../core/projects/project-manager.js";
import Database from "better-sqlite3";
import { join } from "path";
import { existsSync, mkdirSync } from "fs";
const VERSION = "0.3.13";
UpdateChecker.checkForUpdates(VERSION, true).catch(() => {
});
program.name("stackmemory").description(
  "Lossless memory runtime for AI coding tools - organizes context as a call stack instead of linear chat logs, with team collaboration and infinite retention"
).version(VERSION);
program.command("init").description("Initialize StackMemory in current project").action(async () => {
  try {
    const projectRoot = process.cwd();
    const dbDir = join(projectRoot, ".stackmemory");
    if (!existsSync(dbDir)) {
      mkdirSync(dbDir, { recursive: true });
    }
    const dbPath = join(dbDir, "context.db");
    const db = new Database(dbPath);
    new FrameManager(db, "cli-project");
    logger.info("StackMemory initialized successfully", { projectRoot });
    console.log("\u2705 StackMemory initialized in", projectRoot);
    db.close();
  } catch (error) {
    logger.error("Failed to initialize StackMemory", error);
    console.error("\u274C Initialization failed:", error.message);
    process.exit(1);
  }
});
program.command("status").description("Show current StackMemory status").option("--all", "Show all active frames across sessions").option("--project", "Show all active frames in current project").option("--session <id>", "Show frames for specific session").action(async (options) => {
  try {
    const projectRoot = process.cwd();
    const dbPath = join(projectRoot, ".stackmemory", "context.db");
    if (!existsSync(dbPath)) {
      console.log(
        '\u274C StackMemory not initialized. Run "stackmemory init" first.'
      );
      return;
    }
    await UpdateChecker.checkForUpdates(VERSION);
    await sessionManager.initialize();
    await sharedContextLayer.initialize();
    const session = await sessionManager.getOrCreateSession({
      projectPath: projectRoot,
      sessionId: options.session
    });
    const contextDiscovery = await sharedContextLayer.autoDiscoverContext();
    if (contextDiscovery.hasSharedContext && contextDiscovery.sessionCount > 1) {
      console.log(`
\u{1F4A1} Shared Context Available:`);
      console.log(
        `   ${contextDiscovery.sessionCount} sessions with shared context`
      );
      if (contextDiscovery.recentPatterns.length > 0) {
        console.log(`   Recent patterns:`);
        contextDiscovery.recentPatterns.slice(0, 3).forEach((p) => {
          console.log(
            `     \u2022 ${p.type}: ${p.pattern.slice(0, 50)} (${p.frequency}x)`
          );
        });
      }
      if (contextDiscovery.lastDecisions.length > 0) {
        console.log(
          `   Last decision: ${contextDiscovery.lastDecisions[0].decision.slice(0, 60)}`
        );
      }
    }
    const db = new Database(dbPath);
    const frameManager = new FrameManager(db, session.projectId);
    if (options.all) {
      frameManager.setQueryMode(FrameQueryMode.ALL_ACTIVE);
    } else if (options.project) {
      frameManager.setQueryMode(FrameQueryMode.PROJECT_ACTIVE);
    }
    const activeFrames = frameManager.getActiveFramePath();
    const stackDepth = frameManager.getStackDepth();
    const totalStats = db.prepare(
      `
        SELECT 
          COUNT(*) as total_frames,
          SUM(CASE WHEN state = 'active' THEN 1 ELSE 0 END) as active_frames,
          SUM(CASE WHEN state = 'closed' THEN 1 ELSE 0 END) as closed_frames,
          COUNT(DISTINCT run_id) as total_sessions
        FROM frames
        WHERE project_id = ?
      `
    ).get(session.projectId);
    const contextCount = db.prepare(
      `
        SELECT COUNT(*) as count FROM contexts
      `
    ).get();
    const eventCount = db.prepare(
      `
        SELECT COUNT(*) as count FROM events e
        JOIN frames f ON e.frame_id = f.frame_id
        WHERE f.project_id = ?
      `
    ).get(session.projectId);
    console.log("\u{1F4CA} StackMemory Status:");
    console.log(
      `   Session: ${session.sessionId.slice(0, 8)} (${session.state}, ${Math.round((Date.now() - session.startedAt) / 1e3 / 60)}min old)`
    );
    console.log(`   Project: ${session.projectId}`);
    if (session.branch) {
      console.log(`   Branch: ${session.branch}`);
    }
    console.log(`
   Database Statistics (this project):`);
    console.log(
      `     Frames: ${totalStats.total_frames || 0} (${totalStats.active_frames || 0} active, ${totalStats.closed_frames || 0} closed)`
    );
    console.log(`     Events: ${eventCount.count || 0}`);
    console.log(`     Sessions: ${totalStats.total_sessions || 0}`);
    console.log(`     Cached contexts: ${contextCount.count || 0} (global)`);
    const recentFrames = db.prepare(
      `
        SELECT name, type, state, datetime(created_at, 'unixepoch') as created
        FROM frames
        WHERE project_id = ?
        ORDER BY created_at DESC
        LIMIT 3
      `
    ).all(session.projectId);
    if (recentFrames.length > 0) {
      console.log(`
   Recent Activity:`);
      recentFrames.forEach((f) => {
        const stateIcon = f.state === "active" ? "\u{1F7E2}" : "\u26AB";
        console.log(`     ${stateIcon} ${f.name} [${f.type}] - ${f.created}`);
      });
    }
    console.log(`
   Current Session:`);
    console.log(`     Stack depth: ${stackDepth}`);
    console.log(`     Active frames: ${activeFrames.length}`);
    if (activeFrames.length > 0) {
      activeFrames.forEach((frame, i) => {
        const indent = "     " + "  ".repeat(frame.depth || i);
        const prefix = i === 0 ? "\u2514\u2500" : "  \u2514\u2500";
        console.log(`${indent}${prefix} ${frame.name} [${frame.type}]`);
      });
    }
    if (!options.all && !options.project) {
      const otherSessions = await sessionManager.listSessions({
        projectId: session.projectId,
        state: "active"
      });
      const otherActive = otherSessions.filter(
        (s) => s.sessionId !== session.sessionId
      );
      if (otherActive.length > 0) {
        console.log(`
   Other Active Sessions (same project):`);
        otherActive.forEach((s) => {
          const age = Math.round(
            (Date.now() - s.lastActiveAt) / 1e3 / 60 / 60
          );
          console.log(
            `     - ${s.sessionId.slice(0, 8)}: ${s.branch || "main"}, ${age}h old`
          );
        });
        console.log(`
   Tip: Use --all to see frames across sessions`);
      }
    }
    db.close();
  } catch (error) {
    logger.error("Failed to get status", error);
    console.error("\u274C Status check failed:", error.message);
    process.exit(1);
  }
});
const linearCommand = program.command("linear").description("Linear API integration commands");
linearCommand.command("setup").description("Setup Linear OAuth integration").action(async () => {
  try {
    const projectRoot = process.cwd();
    const linearSetup = new LinearOAuthSetup(projectRoot);
    const { authUrl, instructions } = await linearSetup.setupInteractive();
    console.log("\u{1F517} Linear OAuth Setup\n");
    instructions.forEach((instruction) => {
      console.log(instruction);
    });
    if (authUrl) {
      console.log("\n\u{1F4CB} Next step: Complete authorization and run:");
      console.log("stackmemory linear authorize <auth-code>");
    }
  } catch (error) {
    logger.error("Linear setup failed", error);
    console.error("\u274C Setup failed:", error.message);
    process.exit(1);
  }
});
linearCommand.command("authorize").description("Complete Linear OAuth authorization").argument("<code>", "Authorization code from Linear").action(async (authCode) => {
  try {
    const projectRoot = process.cwd();
    const linearSetup = new LinearOAuthSetup(projectRoot);
    const success = await linearSetup.completeAuth(authCode);
    if (success) {
      console.log("\u2705 Linear integration authorized successfully!");
      console.log("\u{1F9EA} Testing connection...");
      const connectionOk = await linearSetup.testConnection();
      if (connectionOk) {
        console.log("\u2705 Linear connection test passed!");
        console.log("\n\u{1F680} You can now use:");
        console.log("- stackmemory linear sync");
        console.log("- stackmemory linear status");
      } else {
        console.log(
          "\u26A0\uFE0F Linear connection test failed. Check your configuration."
        );
      }
    } else {
      console.error("\u274C Authorization failed. Please try again.");
      process.exit(1);
    }
  } catch (error) {
    logger.error("Linear authorization failed", error);
    console.error("\u274C Authorization failed:", error.message);
    process.exit(1);
  }
});
linearCommand.command("status").description("Show Linear integration status").action(async () => {
  try {
    const projectRoot = process.cwd();
    const authManager = new LinearAuthManager(projectRoot);
    const isConfigured = authManager.isConfigured();
    console.log("\u{1F4CA} Linear Integration Status:");
    console.log(`   Configured: ${isConfigured ? "\u2705" : "\u274C"}`);
    if (isConfigured) {
      const config = authManager.loadConfig();
      const tokens = authManager.loadTokens();
      console.log(
        `   Client ID: ${config?.clientId ? config.clientId.substring(0, 8) + "..." : "Not set"}`
      );
      console.log(`   Tokens: ${tokens ? "\u2705 Valid" : "\u274C Missing"}`);
      if (tokens) {
        const expiresIn = Math.floor(
          (tokens.expiresAt - Date.now()) / 1e3 / 60
        );
        console.log(
          `   Token expires: ${expiresIn > 0 ? `${expiresIn} minutes` : "Expired"}`
        );
      }
      console.log("\n\u{1F9EA} Testing connection...");
      const linearSetup = new LinearOAuthSetup(projectRoot);
      const connectionOk = await linearSetup.testConnection();
      console.log(`   Connection: ${connectionOk ? "\u2705 OK" : "\u274C Failed"}`);
    } else {
      console.log('\n\u{1F4A1} Run "stackmemory linear setup" to get started');
    }
  } catch (error) {
    logger.error("Linear status check failed", error);
    console.error("\u274C Status check failed:", error.message);
    process.exit(1);
  }
});
linearCommand.command("sync").description("Sync tasks with Linear").option(
  "-d, --direction <direction>",
  "Sync direction: bidirectional, to_linear, from_linear",
  "bidirectional"
).action(async (options) => {
  try {
    const projectRoot = process.cwd();
    const dbPath = join(projectRoot, ".stackmemory", "context.db");
    if (!existsSync(dbPath)) {
      console.log(
        '\u274C StackMemory not initialized. Run "stackmemory init" first.'
      );
      return;
    }
    const authManager = new LinearAuthManager(projectRoot);
    if (!process.env["LINEAR_API_KEY"] && !authManager.isConfigured()) {
      console.log(
        '\u274C Linear not configured. Set LINEAR_API_KEY environment variable or run "stackmemory linear setup" first.'
      );
      return;
    }
    const db = new Database(dbPath);
    const taskStore = new LinearTaskManager(projectRoot, db);
    const syncConfig = {
      ...DEFAULT_SYNC_CONFIG,
      enabled: true,
      direction: options.direction
    };
    const linearSync = new LinearSyncEngine(
      taskStore,
      authManager,
      syncConfig
    );
    console.log(`\u{1F504} Starting ${options.direction} sync with Linear...`);
    const result = await linearSync.sync();
    const progress = new ProgressTracker(projectRoot);
    if (result.success) {
      console.log("\u2705 Sync completed successfully!");
      console.log(`   To Linear: ${result.synced.toLinear} created`);
      console.log(`   From Linear: ${result.synced.fromLinear} created`);
      console.log(`   Updated: ${result.synced.updated}`);
      progress.updateLinearStatus({
        lastSync: (/* @__PURE__ */ new Date()).toISOString(),
        tasksSynced: result.synced.toLinear + result.synced.fromLinear + result.synced.updated
      });
      if (result.conflicts.length > 0) {
        console.log(`
\u26A0\uFE0F Conflicts detected: ${result.conflicts.length}`);
        result.conflicts.forEach((conflict) => {
          console.log(`   - ${conflict.taskId}: ${conflict.reason}`);
        });
      }
    } else {
      console.log("\u274C Sync failed");
      if (result.errors.length > 0) {
        result.errors.forEach((error) => {
          console.log(`   Error: ${error}`);
        });
      }
    }
    db.close();
  } catch (error) {
    logger.error("Linear sync failed", error);
    console.error("\u274C Sync failed:", error.message);
    process.exit(1);
  }
});
linearCommand.command("auto-sync").description("Manage automatic synchronization").option("--start", "Start auto-sync service").option("--stop", "Stop auto-sync service").option("--status", "Show auto-sync status").option("--interval <minutes>", "Set sync interval in minutes", "5").option(
  "--direction <direction>",
  "Set sync direction: bidirectional, to_linear, from_linear",
  "bidirectional"
).option("--quiet-start <hour>", "Start of quiet hours (0-23)", "22").option("--quiet-end <hour>", "End of quiet hours (0-23)", "7").action(async (options) => {
  try {
    const projectRoot = process.cwd();
    if (options.status) {
      const service = getAutoSyncService();
      if (service) {
        const status = service.getStatus();
        console.log("\u{1F4CA} Linear Auto-Sync Status:");
        console.log(`   Running: ${status.running ? "\u2705" : "\u274C"}`);
        console.log(`   Direction: ${status.config.direction}`);
        console.log(`   Interval: ${status.config.interval} minutes`);
        console.log(
          `   Conflict Resolution: ${status.config.conflictResolution}`
        );
        if (status.lastSyncTime > 0) {
          const lastSync = new Date(status.lastSyncTime);
          console.log(`   Last Sync: ${lastSync.toLocaleString()}`);
        }
        if (status.nextSyncTime) {
          const nextSync = new Date(status.nextSyncTime);
          console.log(`   Next Sync: ${nextSync.toLocaleString()}`);
        }
        if (status.config.quietHours) {
          console.log(
            `   Quiet Hours: ${status.config.quietHours.start}:00 - ${status.config.quietHours.end}:00`
          );
        }
        if (status.retryCount > 0) {
          console.log(`   \u26A0\uFE0F  Retry Count: ${status.retryCount}`);
        }
      } else {
        console.log("\u{1F4CA} Linear Auto-Sync Status: \u274C Not running");
      }
      return;
    }
    if (options.start) {
      const authManager = new LinearAuthManager(projectRoot);
      if (!authManager.isConfigured()) {
        console.log(
          '\u274C Linear not configured. Run "stackmemory linear setup" first.'
        );
        return;
      }
      const config = {
        interval: parseInt(options.interval),
        direction: options.direction,
        quietHours: {
          start: parseInt(options.quietStart),
          end: parseInt(options.quietEnd)
        }
      };
      const service = initializeAutoSync(projectRoot, config);
      await service.start();
      console.log("\u2705 Linear auto-sync started");
      console.log(`   Interval: ${config.interval} minutes`);
      console.log(`   Direction: ${config.direction}`);
      console.log(
        `   Quiet Hours: ${config.quietHours.start}:00 - ${config.quietHours.end}:00`
      );
      console.log(
        '\n\u{1F4A1} Use "stackmemory linear auto-sync --status" to check status'
      );
      process.on("SIGINT", () => {
        console.log("\n\u{1F6D1} Stopping auto-sync service...");
        service.stop();
        process.exit(0);
      });
      console.log("\u{1F504} Auto-sync running... Press Ctrl+C to stop");
      await new Promise(() => {
      });
    }
    if (options.stop) {
      stopAutoSync();
      console.log("\u{1F6D1} Linear auto-sync stopped");
    }
    if (!options.start && !options.stop && !options.status) {
      console.log("\u{1F4A1} Usage:");
      console.log("  --start     Start auto-sync service");
      console.log("  --stop      Stop auto-sync service");
      console.log("  --status    Show current status");
      console.log(
        "\nExample: stackmemory linear auto-sync --start --interval 10"
      );
    }
  } catch (error) {
    logger.error("Linear auto-sync command failed", error);
    console.error("\u274C Auto-sync failed:", error.message);
    process.exit(1);
  }
});
linearCommand.command("force-sync").description("Force immediate synchronization").action(async () => {
  try {
    const service = getAutoSyncService();
    if (service) {
      console.log("\u{1F504} Forcing immediate sync...");
      await service.forceSync();
      console.log("\u2705 Sync completed");
    } else {
      console.log(
        "\u274C Auto-sync service not running. Use manual sync instead:"
      );
      console.log("   stackmemory linear sync");
    }
  } catch (error) {
    logger.error("Force sync failed", error);
    console.error("\u274C Force sync failed:", error.message);
    process.exit(1);
  }
});
linearCommand.command("update <issueId>").description("Update Linear task status").option(
  "-s, --status <status>",
  "New status (todo, in-progress, done, canceled)"
).option("-t, --title <title>", "Update task title").option("-d, --description <desc>", "Update task description").option(
  "-p, --priority <priority>",
  "Set priority (1=urgent, 2=high, 3=medium, 4=low)"
).action(async (issueId, options) => {
  try {
    const projectRoot = process.cwd();
    const authManager = new LinearAuthManager(projectRoot);
    const tokens = authManager.loadTokens();
    if (!tokens) {
      console.error("\u274C Not authenticated. Run: stackmemory linear setup");
      process.exit(1);
    }
    const { LinearClient } = await import("../integrations/linear/client.js");
    const client = new LinearClient({
      apiKey: tokens.accessToken,
      useBearer: true,
      onUnauthorized: async () => {
        const refreshed = await authManager.refreshAccessToken();
        return refreshed.accessToken;
      }
    });
    let issue = await client.getIssue(issueId);
    if (!issue) {
      issue = await client.findIssueByIdentifier(issueId);
    }
    if (!issue) {
      console.error(`\u274C Issue ${issueId} not found`);
      process.exit(1);
    }
    const updates = {};
    if (options.status) {
      const team = await client.getTeam();
      const states = await client.getWorkflowStates(team.id);
      const statusMap = {
        todo: "unstarted",
        "in-progress": "started",
        done: "completed",
        canceled: "cancelled"
      };
      const targetType = statusMap[options.status.toLowerCase()] || options.status;
      const targetState = states.find(
        (s) => s.type === targetType
      );
      if (!targetState) {
        console.error(`\u274C Invalid status: ${options.status}`);
        console.log("Available states:");
        states.forEach(
          (s) => console.log(`  - ${s.name} (${s.type})`)
        );
        process.exit(1);
      }
      updates.stateId = targetState.id;
    }
    if (options.title) updates.title = options.title;
    if (options.description) updates.description = options.description;
    if (options.priority) updates.priority = parseInt(options.priority);
    const updatedIssue = await client.updateIssue(issue.id, updates);
    console.log(
      `\u2705 Updated ${updatedIssue.identifier}: ${updatedIssue.title}`
    );
    if (options.status) {
      console.log(`   Status: ${updatedIssue.state.name}`);
    }
    console.log(`   ${updatedIssue.url}`);
    console.log("\n\u{1F504} Syncing to local tasks...");
    const dbPath = join(projectRoot, ".stackmemory", "context.db");
    if (existsSync(dbPath)) {
      const db = new Database(dbPath);
      const taskStore = new LinearTaskManager(projectRoot, db);
      const { LinearSyncEngine: LinearSyncEngine2, DEFAULT_SYNC_CONFIG: DEFAULT_SYNC_CONFIG2 } = await import("../integrations/linear/sync.js");
      const syncEngine = new LinearSyncEngine2(
        taskStore,
        authManager,
        { ...DEFAULT_SYNC_CONFIG2, enabled: true, direction: "from_linear" },
        projectRoot
      );
      const syncResult = await syncEngine.sync();
      if (syncResult.success) {
        console.log(
          `   \u2705 Local tasks synced (${syncResult.synced.fromLinear} new, ${syncResult.synced.updated} updated)`
        );
      }
      db.close();
    }
  } catch (error) {
    logger.error("Failed to update Linear task", error);
    console.error("\u274C Failed to update task:", error.message);
    process.exit(1);
  }
});
linearCommand.command("config").description("Configure auto-sync settings").option("--show", "Show current configuration").option("--set-interval <minutes>", "Set sync interval in minutes").option(
  "--set-direction <direction>",
  "Set sync direction: bidirectional, to_linear, from_linear"
).option(
  "--set-conflict-resolution <strategy>",
  "Set conflict resolution: newest_wins, linear_wins, stackmemory_wins, manual"
).option("--set-quiet-start <hour>", "Set start of quiet hours (0-23)").option("--set-quiet-end <hour>", "Set end of quiet hours (0-23)").option("--enable", "Enable auto-sync").option("--disable", "Disable auto-sync").option("--reset", "Reset to default configuration").action(async (options) => {
  try {
    const projectRoot = process.cwd();
    const configManager = new LinearConfigManager(projectRoot);
    if (options.reset) {
      configManager.resetConfig();
      console.log("\u2705 Configuration reset to defaults");
      return;
    }
    if (options.show) {
      const config = configManager.loadConfig();
      if (config) {
        console.log("\u{1F4CA} Linear Auto-Sync Configuration:");
        console.log(`   Enabled: ${config.enabled ? "\u2705" : "\u274C"}`);
        console.log(`   Interval: ${config.interval} minutes`);
        console.log(`   Direction: ${config.direction}`);
        console.log(`   Conflict Resolution: ${config.conflictResolution}`);
        console.log(`   Retry Attempts: ${config.retryAttempts}`);
        console.log(`   Retry Delay: ${config.retryDelay / 1e3}s`);
        if (config.quietHours) {
          console.log(
            `   Quiet Hours: ${config.quietHours.start}:00 - ${config.quietHours.end}:00`
          );
        }
        const lastUpdated = new Date(config.lastUpdated);
        console.log(`   Last Updated: ${lastUpdated.toLocaleString()}`);
      } else {
        console.log("\u{1F4CA} No configuration found. Using defaults.");
        const defaultConfig = configManager.getDefaultConfig();
        console.log(`   Default interval: ${defaultConfig.interval} minutes`);
        console.log(`   Default direction: ${defaultConfig.direction}`);
      }
      return;
    }
    const updates = {};
    if (options.setInterval) {
      const interval = parseInt(options.setInterval);
      if (isNaN(interval) || interval < 1) {
        console.error("\u274C Interval must be a positive number");
        process.exit(1);
      }
      updates.interval = interval;
      console.log(`\u2705 Set interval to ${interval} minutes`);
    }
    if (options.setDirection) {
      const validDirections = ["bidirectional", "to_linear", "from_linear"];
      if (!validDirections.includes(options.setDirection)) {
        console.error(
          `\u274C Invalid direction. Must be one of: ${validDirections.join(", ")}`
        );
        process.exit(1);
      }
      updates.direction = options.setDirection;
      console.log(`\u2705 Set direction to ${options.setDirection}`);
    }
    if (options.setConflictResolution) {
      const validStrategies = [
        "newest_wins",
        "linear_wins",
        "stackmemory_wins",
        "manual"
      ];
      if (!validStrategies.includes(options.setConflictResolution)) {
        console.error(
          `\u274C Invalid strategy. Must be one of: ${validStrategies.join(", ")}`
        );
        process.exit(1);
      }
      updates.conflictResolution = options.setConflictResolution;
      console.log(
        `\u2705 Set conflict resolution to ${options.setConflictResolution}`
      );
    }
    if (options.setQuietStart) {
      const hour = parseInt(options.setQuietStart);
      if (isNaN(hour) || hour < 0 || hour > 23) {
        console.error("\u274C Quiet start hour must be between 0 and 23");
        process.exit(1);
      }
      const currentConfig = configManager.loadConfig() || configManager.getDefaultConfig();
      updates.quietHours = {
        start: hour,
        end: currentConfig.quietHours?.end || 7
      };
      console.log(`\u2705 Set quiet hours start to ${hour}:00`);
    }
    if (options.setQuietEnd) {
      const hour = parseInt(options.setQuietEnd);
      if (isNaN(hour) || hour < 0 || hour > 23) {
        console.error("\u274C Quiet end hour must be between 0 and 23");
        process.exit(1);
      }
      const currentConfig = configManager.loadConfig() || configManager.getDefaultConfig();
      updates.quietHours = {
        start: currentConfig.quietHours?.start || 22,
        end: hour
      };
      console.log(`\u2705 Set quiet hours end to ${hour}:00`);
    }
    if (options.enable) {
      updates.enabled = true;
      console.log("\u2705 Auto-sync enabled");
    }
    if (options.disable) {
      updates.enabled = false;
      console.log("\u274C Auto-sync disabled");
    }
    if (Object.keys(updates).length > 0) {
      configManager.saveConfig(updates);
      console.log(
        "\n\u{1F4A1} Configuration updated. Restart auto-sync service to apply changes."
      );
    } else if (!options.show) {
      console.log("\u{1F4A1} Use --show to view current configuration");
      console.log("\u{1F4A1} Use --help to see all configuration options");
    }
  } catch (error) {
    logger.error("Linear config command failed", error);
    console.error("\u274C Config failed:", error.message);
    process.exit(1);
  }
});
program.command("update-check").description("Check for StackMemory updates").action(async () => {
  try {
    console.log("\u{1F50D} Checking for updates...");
    await UpdateChecker.forceCheck(VERSION);
  } catch (error) {
    logger.error("Update check failed", error);
    console.error("\u274C Update check failed:", error.message);
    process.exit(1);
  }
});
program.command("analytics").description("Launch task analytics dashboard").option("-p, --port <port>", "Port for dashboard server", "3000").option("-o, --open", "Open dashboard in browser").option("--export <format>", "Export metrics (json|csv)").option("--sync", "Sync with Linear before launching").option("--view", "Show analytics in terminal").action(async (options) => {
  try {
    const projectRoot = process.cwd();
    const dbPath = join(projectRoot, ".stackmemory", "context.db");
    if (!existsSync(dbPath)) {
      console.log(
        '\u274C StackMemory not initialized. Run "stackmemory init" first.'
      );
      return;
    }
    if (options.view) {
      const { displayAnalyticsDashboard } = await import("./utils/viewer.js");
      await displayAnalyticsDashboard(projectRoot);
      return;
    }
    if (options.export) {
      const { AnalyticsService } = await import("../features/analytics/index.js");
      const service = new AnalyticsService(projectRoot);
      if (options.sync) {
        console.log("\u{1F504} Syncing with Linear...");
        await service.syncLinearTasks();
      }
      const state = await service.getDashboardState();
      if (options.export === "csv") {
        console.log("\u{1F4CA} Exporting metrics as CSV...");
        const tasks = state.recentTasks;
        const headers = [
          "ID",
          "Title",
          "State",
          "Priority",
          "Created",
          "Completed"
        ];
        const rows = tasks.map((t) => [
          t.id,
          t.title,
          t.state,
          t.priority,
          t.createdAt.toISOString(),
          t.completedAt?.toISOString() || ""
        ]);
        console.log(headers.join(","));
        rows.forEach((r) => console.log(r.join(",")));
      } else {
        console.log(JSON.stringify(state, null, 2));
      }
      service.close();
      return;
    }
    console.log(
      `\u{1F680} Launching analytics dashboard on port ${options.port}...`
    );
    const express = (await import("express")).default;
    const { AnalyticsAPI } = await import("../features/analytics/index.js");
    const { createServer } = await import("http");
    const app = express();
    app.use(
      (err, _req, res, _next) => {
        console.error("Express error:", err);
        res.status(500).json({ error: err.message });
      }
    );
    const analyticsAPI = new AnalyticsAPI(projectRoot);
    if (options.sync) {
      console.log("\u{1F504} Syncing with Linear...");
      const service = new (await import("../features/analytics/index.js")).AnalyticsService(projectRoot);
      await service.syncLinearTasks();
      service.close();
    }
    app.use("/api/analytics", analyticsAPI.getRouter());
    app.get("/", async (req, res) => {
      const possiblePaths = [
        join(projectRoot, "src/features/analytics/dashboard.html"),
        join(projectRoot, "dist/features/analytics/dashboard.html")
      ];
      for (const dashboardPath of possiblePaths) {
        if (existsSync(dashboardPath)) {
          res.sendFile(dashboardPath);
          return;
        }
      }
      res.send(`<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>StackMemory Analytics</title>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #1a1a2e; color: #eee; padding: 20px; }
    .container { max-width: 1200px; margin: 0 auto; }
    h1 { color: #667eea; margin-bottom: 20px; }
    .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; }
    .card { background: #16213e; border-radius: 12px; padding: 20px; }
    .metric-value { font-size: 2.5em; font-weight: bold; color: #667eea; }
    .metric-label { color: #888; text-transform: uppercase; font-size: 0.8em; }
    .task-list { max-height: 400px; overflow-y: auto; }
    .task-item { padding: 10px; border-left: 3px solid #667eea; margin-bottom: 8px; background: #1a1a2e; }
    .task-item.completed { border-color: #22c55e; }
    .task-item.in_progress { border-color: #f59e0b; }
    .status { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 0.8em; margin-right: 8px; }
    .status.completed { background: #22c55e30; color: #22c55e; }
    .status.in_progress { background: #f59e0b30; color: #f59e0b; }
    .status.todo { background: #667eea30; color: #667eea; }
  </style>
</head>
<body>
  <div class="container">
    <h1>\u{1F4CA} StackMemory Analytics</h1>
    <div class="grid" id="metrics"></div>
    <div class="card"><h3>Recent Tasks</h3><div class="task-list" id="tasks">Loading...</div></div>
  </div>
  <script>
    async function load() {
      const metrics = await fetch('/api/analytics/metrics').then(r => r.json());
      const tasks = await fetch('/api/analytics/tasks').then(r => r.json());
      
      document.getElementById('metrics').innerHTML = \`
        <div class="card"><div class="metric-label">Total</div><div class="metric-value">\${metrics.data.metrics.totalTasks}</div></div>
        <div class="card"><div class="metric-label">Completed</div><div class="metric-value">\${metrics.data.metrics.completedTasks}</div></div>
        <div class="card"><div class="metric-label">In Progress</div><div class="metric-value">\${metrics.data.metrics.inProgressTasks}</div></div>
        <div class="card"><div class="metric-label">Completion</div><div class="metric-value">\${metrics.data.metrics.completionRate.toFixed(0)}%</div></div>
      \`;
      
      document.getElementById('tasks').innerHTML = tasks.data.tasks.slice(0, 10).map((t: any) => \`
        <div class="task-item \${t.state}">
          <span class="status \${t.state}">\${t.state}</span>
          <strong>\${t.title}</strong>
        </div>
      \`).join('');
    }
    load();
    setInterval(load, 30000);
  </script>
</body>
</html>`);
    });
    const server = createServer(app);
    analyticsAPI.setupWebSocket(server);
    server.listen(options.port, async () => {
      console.log(
        `\u2705 Analytics dashboard running at http://localhost:${options.port}`
      );
      if (options.open) {
        const { exec } = await import("child_process");
        const url = `http://localhost:${options.port}`;
        const command = process.platform === "darwin" ? `open ${url}` : process.platform === "win32" ? `start ${url}` : `xdg-open ${url}`;
        exec(command);
      }
    });
    process.on("SIGINT", () => {
      console.log("\n\u{1F44B} Shutting down analytics dashboard...");
      analyticsAPI.close();
      server.close();
      process.exit(0);
    });
    await new Promise(() => {
    });
  } catch (error) {
    logger.error("Analytics command failed", error);
    console.error("\u274C Analytics failed:", error.message);
    process.exit(1);
  }
});
program.command("progress").description("Show current progress and recent changes").action(async () => {
  try {
    const projectRoot = process.cwd();
    const dbPath = join(projectRoot, ".stackmemory", "context.db");
    if (!existsSync(dbPath)) {
      console.log(
        '\u274C StackMemory not initialized. Run "stackmemory init" first.'
      );
      return;
    }
    const progress = new ProgressTracker(projectRoot);
    console.log(progress.getSummary());
  } catch (error) {
    logger.error("Failed to show progress", error);
    console.error("\u274C Failed to show progress:", error.message);
    process.exit(1);
  }
});
program.command("mcp-server").description("Start StackMemory MCP server for Claude Desktop").option("-p, --project <path>", "Project root directory", process.cwd()).action(async (options) => {
  try {
    const { runMCPServer } = await import("../integrations/mcp/server.js");
    process.env["PROJECT_ROOT"] = options.project;
    console.log("\u{1F680} Starting StackMemory MCP Server...");
    console.log(`   Project: ${options.project}`);
    console.log(`   Version: ${VERSION}`);
    UpdateChecker.checkForUpdates(VERSION, true).catch(() => {
    });
    await runMCPServer();
  } catch (error) {
    logger.error("Failed to start MCP server", error);
    console.error("\u274C MCP server failed:", error.message);
    process.exit(1);
  }
});
program.command("context:test").description("Test context persistence by creating sample frames").action(async () => {
  try {
    const projectRoot = process.cwd();
    const dbPath = join(projectRoot, ".stackmemory", "context.db");
    if (!existsSync(dbPath)) {
      console.log(
        '\u274C StackMemory not initialized. Run "stackmemory init" first.'
      );
      return;
    }
    const db = new Database(dbPath);
    const frameManager = new FrameManager(db, "cli-project");
    console.log("\u{1F4DD} Creating test context frames...");
    const rootFrame = frameManager.createFrame({
      type: "task",
      name: "Test Session",
      inputs: { test: true, timestamp: (/* @__PURE__ */ new Date()).toISOString() }
    });
    const taskFrame = frameManager.createFrame({
      type: "subtask",
      name: "Sample Task",
      inputs: { description: "Testing context persistence" },
      parentFrameId: rootFrame
    });
    const commandFrame = frameManager.createFrame({
      type: "tool_scope",
      name: "test-command",
      inputs: { args: ["--test"] },
      parentFrameId: taskFrame
    });
    frameManager.addEvent(
      "observation",
      {
        message: "Test event recorded"
      },
      commandFrame
    );
    console.log("\u2705 Test frames created!");
    console.log(`\u{1F4CA} Stack depth: ${frameManager.getStackDepth()}`);
    console.log(
      `\u{1F504} Active frames: ${frameManager.getActiveFramePath().length}`
    );
    frameManager.closeFrame(commandFrame);
    console.log(
      `\u{1F4CA} After closing command frame: depth = ${frameManager.getStackDepth()}`
    );
    db.close();
  } catch (error) {
    logger.error("Test context failed", error);
    console.error("\u274C Test failed:", error.message);
    process.exit(1);
  }
});
registerOnboardingCommand(program);
registerProjectCommands(program);
registerWorktreeCommands(program);
registerLinearCommands(program);
registerLinearTestCommand(program);
registerLinearListCommand(program);
registerLinearMigrateCommand(program);
registerLinearCreateCommand(program);
program.addCommand(createChromaDBCommand());
program.addCommand(createInfiniteStorageCommand());
program.addCommand(createGCCommand());
program.addCommand(createSessionCommands());
program.addCommand(webhookCommand());
program.addCommand(createTaskCommands());
program.addCommand(createSearchCommand());
program.addCommand(createLogCommand());
program.addCommand(createContextCommands());
program.addCommand(createConfigCommand());
program.addCommand(createAgentCommand());
program.addCommand(createHandoffCommand());
program.addCommand(createStorageCommand());
program.addCommand(createSkillsCommand());
program.addCommand(createTestCommand());
program.addCommand(clearCommand);
program.addCommand(createWorkflowCommand());
program.addCommand(monitorCommand);
program.addCommand(qualityCommand);
program.command("dashboard").description("Display monitoring dashboard in terminal").option("-w, --watch", "Auto-refresh dashboard").option("-i, --interval <seconds>", "Refresh interval in seconds", "5").action(async (options) => {
  const { dashboardCommand } = await import("./commands/dashboard.js");
  await dashboardCommand.handler(options);
});
program.command("tui").description("Launch interactive TUI monitoring dashboard (requires blessed)").option("-s, --server", "Start WebSocket server for real-time updates").option("-w, --ws-url <url>", "WebSocket server URL", "ws://localhost:8080").option("-r, --refresh <ms>", "Auto-refresh interval in milliseconds", "2000").action(async (options) => {
  try {
    try {
      await import("blessed");
    } catch {
      console.log(
        "\u274C The TUI requires the blessed package. Install it with:"
      );
      console.log("   npm install blessed blessed-contrib");
      console.log(
        '\n\u{1F4A1} Alternatively, use "stackmemory dashboard" for a simpler view'
      );
      process.exit(1);
    }
    const { spawn } = await import("child_process");
    const { fileURLToPath } = await import("url");
    const { dirname, join: join2 } = await import("path");
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = dirname(__filename);
    console.log("\u{1F680} Launching StackMemory TUI Dashboard...");
    process.env["STACKMEMORY_WS_URL"] = options.wsUrl;
    const tuiPath = join2(__dirname, "../features/tui/index.js");
    const tui = spawn("node", [tuiPath], {
      stdio: "inherit",
      env: {
        ...process.env,
        STACKMEMORY_WS_URL: options.wsUrl
      }
    });
    tui.on("error", (error) => {
      console.error("Failed to launch TUI:", error);
      console.log('\n\u{1F4A1} Try "stackmemory dashboard" instead');
      process.exit(1);
    });
    tui.on("exit", (code) => {
      if (code !== 0) {
        console.error(`TUI exited with code ${code}`);
        process.exit(code || 1);
      }
    });
  } catch (error) {
    console.error("\u274C Failed to launch TUI:", error.message);
    console.log('\n\u{1F4A1} Try "stackmemory dashboard" for a simpler view');
    process.exit(1);
  }
});
if (process.argv.length > 2) {
  const manager = ProjectManager.getInstance();
  manager.detectProject().catch(() => {
  });
}
const isMainModule = import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith("/stackmemory") || process.argv[1]?.endsWith("index.ts") || process.argv[1]?.includes("tsx");
if (isMainModule) {
  program.parse();
}
export {
  program
};
//# sourceMappingURL=index.js.map
