"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var tools_exports = {};
__export(tools_exports, {
  KIROGRAPH_TOOL_NAMES: () => import_tool_names.KIROGRAPH_TOOL_NAMES,
  ToolHandler: () => ToolHandler,
  tools: () => tools
});
module.exports = __toCommonJS(tools_exports);
var fs = __toESM(require("fs"));
var path = __toESM(require("path"));
var crypto = __toESM(require("crypto"));
var import_child_process = require("child_process");
var import__ = __toESM(require("../index"));
var import_errors = require("../errors");
var import_compression = require("../compression/index");
var import_tracker = require("../compression/tracker");
var import_tool_names = require("./tool-names");
const MAX_OUTPUT = 15e3;
function truncate(s) {
  return s.length > MAX_OUTPUT ? s.slice(0, MAX_OUTPUT) + "\n\u2026[truncated]" : s;
}
function clampLimit(value, defaultValue) {
  const n = typeof value === "number" ? value : defaultValue;
  return Math.max(1, Math.min(100, Math.round(n)));
}
function mapKind(kind) {
  if (kind === "type_alias") return "type";
  return kind;
}
function writeSessionMarker(projectRoot) {
  try {
    const hash = crypto.createHash("sha256").update(projectRoot).digest("hex").slice(0, 16);
    fs.writeFileSync(`/tmp/kirograph-consulted-${hash}`, String(Date.now()));
  } catch {
  }
}
function formatAge(timestamp) {
  const diff = Date.now() - timestamp;
  const minutes = Math.floor(diff / 6e4);
  if (minutes < 60) return `${minutes}m ago`;
  const hours = Math.floor(minutes / 60);
  if (hours < 24) return `${hours}h ago`;
  const days = Math.floor(hours / 24);
  if (days < 7) return `${days}d ago`;
  const weeks = Math.floor(days / 7);
  if (weeks < 5) return `${weeks}w ago`;
  const months = Math.floor(days / 30);
  return `${months}mo ago`;
}
const tools = [
  {
    name: "kirograph_search",
    description: "Quick symbol search by name. Returns locations only (no code). Use kirograph_context for comprehensive task context.",
    inputSchema: {
      type: "object",
      properties: {
        query: { type: "string", description: 'Symbol name or partial name (e.g., "auth", "signIn", "UserService")' },
        kind: {
          type: "string",
          description: "Filter by node kind",
          enum: ["function", "method", "class", "interface", "type_alias", "variable", "route", "component"]
        },
        limit: { type: "number", description: "Max results 1-100 (default: 10)", default: 10 },
        projectPath: { type: "string", description: "Project root path (optional, defaults to current project)" }
      },
      required: ["query"]
    }
  },
  {
    name: "kirograph_context",
    description: "PRIMARY TOOL: Build comprehensive context for a task or feature request. Returns entry points, related symbols, and key code \u2014 often enough to understand the codebase without additional tool calls.",
    inputSchema: {
      type: "object",
      properties: {
        task: { type: "string", description: "Description of the task, bug, or feature to build context for" },
        maxNodes: { type: "number", description: "Max symbols to include (default: 20)", default: 20 },
        includeCode: { type: "boolean", description: "Include code snippets (default: true)", default: true },
        projectPath: { type: "string", description: "Project root path (optional, defaults to current project)" }
      },
      required: ["task"]
    }
  },
  {
    name: "kirograph_callers",
    description: "Find all functions/methods that call a specific symbol.",
    inputSchema: {
      type: "object",
      properties: {
        symbol: { type: "string", description: "Symbol name to find callers for" },
        limit: { type: "number", description: "Max results 1-100 (default: 20)", default: 20 },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["symbol"]
    }
  },
  {
    name: "kirograph_callees",
    description: "Find all functions/methods that a specific symbol calls.",
    inputSchema: {
      type: "object",
      properties: {
        symbol: { type: "string", description: "Symbol name to find callees for" },
        limit: { type: "number", description: "Max results 1-100 (default: 20)", default: 20 },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["symbol"]
    }
  },
  {
    name: "kirograph_impact",
    description: "Analyze what code would be affected by changing a symbol. Use before making changes.",
    inputSchema: {
      type: "object",
      properties: {
        symbol: { type: "string", description: "Symbol name to analyze impact for" },
        depth: { type: "number", description: "Traversal depth (default: 2)", default: 2 },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["symbol"]
    }
  },
  {
    name: "kirograph_node",
    description: "Get details about a specific symbol, optionally including its source code.",
    inputSchema: {
      type: "object",
      properties: {
        symbol: { type: "string", description: "Symbol name to look up" },
        includeCode: { type: "boolean", description: "Include source code (default: false)", default: false },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["symbol"]
    }
  },
  {
    name: "kirograph_status",
    description: "Check index health and statistics.",
    inputSchema: {
      type: "object",
      properties: {
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  {
    name: "kirograph_files",
    description: "List the indexed file structure of the project. Supports filtering by path prefix, glob pattern, or depth.",
    inputSchema: {
      type: "object",
      properties: {
        filterPath: { type: "string", description: 'Filter by directory path prefix (e.g., "src/")' },
        pattern: { type: "string", description: 'Filter by glob pattern (e.g., "**/*.ts")' },
        maxDepth: { type: "number", description: "Limit tree depth" },
        format: {
          type: "string",
          description: 'Output format: "tree" (default, visual tree), "flat" (one path per line), "grouped" (grouped by directory), "compact" (rtk-style summary with counts)',
          enum: ["tree", "flat", "grouped", "compact"],
          default: "tree"
        },
        includeMetadata: { type: "boolean", description: "Include language and symbol count (default: true)", default: true },
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  {
    name: "kirograph_dead_code",
    description: "Find symbols with no incoming references (potential dead code). Only includes unexported symbols.",
    inputSchema: {
      type: "object",
      properties: {
        limit: { type: "number", description: "Max results 1-100 (default: 50)", default: 50 },
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  {
    name: "kirograph_circular_deps",
    description: "Find circular import dependencies in the codebase.",
    inputSchema: {
      type: "object",
      properties: {
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  {
    name: "kirograph_path",
    description: "Find the shortest path between two symbols in the graph.",
    inputSchema: {
      type: "object",
      properties: {
        from: { type: "string", description: "Source symbol name" },
        to: { type: "string", description: "Target symbol name" },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["from", "to"]
    }
  },
  {
    name: "kirograph_architecture",
    description: "Get the high-level software architecture: packages, layers, and their dependencies. Requires enableArchitecture=true in config. Call this first on a new task to orient yourself without reading files.",
    inputSchema: {
      type: "object",
      properties: {
        level: {
          type: "string",
          description: 'View level: "packages" (package graph), "layers" (architectural layers), or "both" (default)',
          enum: ["packages", "layers", "both"],
          default: "both"
        },
        includeFiles: { type: "boolean", description: "Include per-file package/layer assignments (default: false)", default: false },
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  {
    name: "kirograph_coupling",
    description: "Show coupling metrics for packages: afferent (Ca), efferent (Ce), and instability (Ce/(Ca+Ce)). High instability = depends on many others; low instability = depended on by many. Requires enableArchitecture=true.",
    inputSchema: {
      type: "object",
      properties: {
        sortBy: {
          type: "string",
          description: 'Sort order: "instability" (default), "afferent", or "efferent"',
          enum: ["instability", "afferent", "efferent"],
          default: "instability"
        },
        limit: { type: "number", description: "Max results (default: 20)", default: 20 },
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  {
    name: "kirograph_package",
    description: "Drill into one package: files it contains, symbols it exports, packages it depends on, and packages that depend on it. Requires enableArchitecture=true.",
    inputSchema: {
      type: "object",
      properties: {
        package: { type: "string", description: "Package name or path (partial match accepted)" },
        includeFiles: { type: "boolean", description: "List files in the package (default: true)", default: true },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["package"]
    }
  },
  {
    name: "kirograph_hotspots",
    description: "Find the most-connected symbols in the codebase by total edge degree (incoming + outgoing). Useful for identifying load-bearing code, core abstractions, or blast-radius hot zones.",
    inputSchema: {
      type: "object",
      properties: {
        limit: { type: "number", description: "Max results 1-100 (default: 20)", default: 20 },
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  {
    name: "kirograph_surprising",
    description: "Find non-obvious cross-file connections: direct edges between symbols in structurally distant parts of the codebase. High-score pairs indicate unexpected coupling worth investigating.",
    inputSchema: {
      type: "object",
      properties: {
        limit: { type: "number", description: "Max results 1-100 (default: 20)", default: 20 },
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  {
    name: "kirograph_diff",
    description: "Compare the current graph against a saved snapshot. Shows added/removed symbols and relationships since the snapshot was taken. Use `kirograph snapshot` CLI command to save a snapshot first.",
    inputSchema: {
      type: "object",
      properties: {
        snapshot: { type: "string", description: "Snapshot label to compare against. Omit to use the latest saved snapshot." },
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  {
    name: "kirograph_type_hierarchy",
    description: "Traverse the type hierarchy of a class or interface (base types and derived types).",
    inputSchema: {
      type: "object",
      properties: {
        symbol: { type: "string", description: "Class or interface name" },
        direction: {
          type: "string",
          description: 'Direction: "up" for base types, "down" for derived types, "both" for all (default)',
          enum: ["up", "down", "both"],
          default: "both"
        },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["symbol"]
    }
  },
  {
    name: "kirograph_exec",
    description: "Run a shell command and return token-optimized output. Automatically filters noise from git, test runners, linters, build tools, docker, and package managers. Use instead of raw shell for 60-90% token savings on verbose commands.",
    inputSchema: {
      type: "object",
      properties: {
        command: { type: "string", description: 'Shell command to execute (e.g., "git status", "npm test", "cargo build")' },
        cwd: { type: "string", description: "Working directory (default: project root)" },
        level: {
          type: "string",
          description: 'Compression level: "normal" (balanced), "aggressive" (more compact), "ultra" (maximum compression)',
          enum: ["normal", "aggressive", "ultra"],
          default: "normal"
        },
        timeout: { type: "number", description: "Timeout in seconds (default: 60)", default: 60 },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["command"]
    }
  },
  {
    name: "kirograph_gain",
    description: "Show token savings statistics \u2014 both from graph tools (vs manual file reads/grep) and from kirograph_exec shell compression.",
    inputSchema: {
      type: "object",
      properties: {
        period: {
          type: "string",
          description: 'Time period: "session" (current), "today", "week", or "all"',
          enum: ["session", "today", "week", "all"],
          default: "session"
        },
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  // ── Memory tools (require enableMemory=true) ────────────────────────────────
  {
    name: "kirograph_mem_search",
    description: "Search project memory for past decisions, errors, patterns, and context. Returns observations ranked by relevance.",
    inputSchema: {
      type: "object",
      properties: {
        query: { type: "string", description: "Natural language search query" },
        kind: {
          type: "string",
          description: "Filter by observation kind",
          enum: ["decision", "error", "pattern", "architecture", "summary", "note"]
        },
        limit: { type: "number", description: "Max results (default: 10)", default: 10 },
        sessionId: { type: "string", description: "Filter to specific session" },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["query"]
    }
  },
  {
    name: "kirograph_mem_store",
    description: "Store an observation in project memory. Content is automatically compressed (if caveman mode is on) and linked to relevant code symbols.",
    inputSchema: {
      type: "object",
      properties: {
        content: { type: "string", description: "Observation text" },
        kind: {
          type: "string",
          description: "Observation kind",
          enum: ["decision", "error", "pattern", "architecture", "summary", "note"],
          default: "note"
        },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["content"]
    }
  },
  {
    name: "kirograph_mem_timeline",
    description: "List recent sessions and their observations chronologically.",
    inputSchema: {
      type: "object",
      properties: {
        limit: { type: "number", description: "Number of sessions to show (default: 5)", default: 5 },
        sessionId: { type: "string", description: "Show observations for a specific session" },
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  {
    name: "kirograph_mem_status",
    description: "Memory subsystem health: session count, observations, embedding coverage, storage size.",
    inputSchema: {
      type: "object",
      properties: {
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  // ── Docs tools (require enableDocs=true) ────────────────────────────────────
  {
    name: "kirograph_docs_toc",
    description: "Get table of contents for a documentation file or the whole project. Returns section IDs, titles, levels, and summaries.",
    inputSchema: {
      type: "object",
      properties: {
        file: { type: "string", description: "Filter to a specific doc file (relative path). Omit for project-wide TOC." },
        tree: { type: "boolean", description: "Return nested tree structure (default: false, flat list)", default: false },
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  },
  {
    name: "kirograph_docs_search",
    description: "Search documentation sections by query. Returns matching sections ranked by relevance. Independent from kirograph_search (code-only).",
    inputSchema: {
      type: "object",
      properties: {
        query: { type: "string", description: "Search query (natural language or keywords)" },
        file: { type: "string", description: "Narrow search to a specific doc file (relative path)" },
        limit: { type: "number", description: "Max results (default: 10)", default: 10 },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["query"]
    }
  },
  {
    name: "kirograph_docs_section",
    description: "Retrieve full content of a documentation section by its stable ID. Use context=true to also get ancestor headings and child summaries.",
    inputSchema: {
      type: "object",
      properties: {
        id: { type: "string", description: "Section ID (from kirograph_docs_toc or kirograph_docs_search results)" },
        context: { type: "boolean", description: "Include ancestor heading chain and child summaries (default: false)", default: false },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["id"]
    }
  },
  {
    name: "kirograph_docs_outline",
    description: "Get the heading hierarchy for a single documentation file. Lighter than full TOC when you know which file is relevant.",
    inputSchema: {
      type: "object",
      properties: {
        file: { type: "string", description: "Relative path to the doc file" },
        projectPath: { type: "string", description: "Project root path (optional)" }
      },
      required: ["file"]
    }
  },
  {
    name: "kirograph_docs_refs",
    description: "Find code symbols referenced by a doc section, or doc sections that reference a code symbol. Bidirectional lookup.",
    inputSchema: {
      type: "object",
      properties: {
        sectionId: { type: "string", description: "Doc section ID (find code symbols it references)" },
        nodeId: { type: "string", description: "Code symbol qualified name (find doc sections that reference it)" },
        projectPath: { type: "string", description: "Project root path (optional)" }
      }
    }
  }
];
class ToolHandler {
  constructor(cg) {
    this.connections = /* @__PURE__ */ new Map();
    this.defaultCg = cg;
  }
  setDefaultKiroGraph(cg) {
    this.defaultCg = cg;
  }
  /** Close all cached cross-project connections. */
  closeAll() {
    for (const cg of this.connections.values()) {
      try {
        cg.close();
      } catch {
      }
    }
    this.connections.clear();
  }
  async getConnection(projectPath) {
    if (!projectPath) return this.defaultCg;
    const resolved = path.resolve(projectPath);
    if (this.connections.has(resolved)) return this.connections.get(resolved);
    try {
      const cg = await import__.default.open(resolved);
      this.connections.set(resolved, cg);
      return cg;
    } catch {
      return null;
    }
  }
  async handle(toolName, args) {
    try {
      const text = await this.dispatch(toolName, args);
      const truncated = truncate(text);
      if (toolName !== "kirograph_exec" && toolName !== "kirograph_gain") {
        try {
          const projectRoot = args.projectPath || this.defaultCg?.getProjectRoot() || process.cwd();
          const { estimateNaiveCost } = await Promise.resolve().then(() => require("../compression/naive-cost.js"));
          const { estimateTokens: estimateTokens2 } = await Promise.resolve().then(() => require("../compression/index.js"));
          const outputTokens = estimateTokens2(truncated);
          const naiveCost = estimateNaiveCost(toolName, outputTokens, args);
          if (naiveCost !== null && naiveCost > outputTokens) {
            const tracker = new import_tracker.TokenTracker(projectRoot);
            if (toolName.startsWith("kirograph_mem_")) {
              tracker.recordMemorySaving(toolName, outputTokens, naiveCost);
            } else if (toolName.startsWith("kirograph_docs_")) {
              tracker.recordDocsSaving(toolName, outputTokens, naiveCost);
            } else {
              tracker.recordGraphSaving(toolName, outputTokens, naiveCost);
            }
          }
        } catch {
        }
      }
      return { content: [{ type: "text", text: truncated }] };
    } catch (err) {
      (0, import_errors.logError)("MCP tool error", { tool: toolName, error: err });
      const message = err instanceof Error ? err.message : String(err);
      return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
    }
  }
  async dispatch(toolName, args) {
    if (toolName === "kirograph_exec") {
      const cmd = args.command;
      if (!cmd) return "Error: command is required.";
      const projectRoot = args.projectPath || args.cwd || process.cwd();
      const execCwd = args.cwd || projectRoot;
      let defaultLevel = "normal";
      try {
        const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
        const config = await loadConfig(projectRoot);
        if (config.shellCompressionLevel && config.shellCompressionLevel !== "off") {
          defaultLevel = config.shellCompressionLevel;
        }
      } catch {
      }
      const level = args.level ?? defaultLevel;
      const timeout = (args.timeout ?? 60) * 1e3;
      let rawOutput;
      let exitCode = 0;
      try {
        rawOutput = (0, import_child_process.execSync)(cmd, {
          cwd: execCwd,
          timeout,
          encoding: "utf8",
          stdio: ["pipe", "pipe", "pipe"],
          maxBuffer: 10 * 1024 * 1024
        });
      } catch (err) {
        rawOutput = (err.stdout || "") + (err.stderr || "");
        exitCode = err.status ?? 1;
      }
      const result = (0, import_compression.compress)(cmd, rawOutput, { level, preserveErrors: exitCode !== 0 });
      const tracker = new import_tracker.TokenTracker(projectRoot);
      tracker.record(cmd, result.originalTokens, result.compressedTokens, result.strategy);
      const header = exitCode !== 0 ? `[exit ${exitCode}] ` : "";
      const footer = result.savings > 5 ? `

[${result.savings}% tokens saved | ${result.originalTokens}\u2192${result.compressedTokens} | ${result.strategy}]` : "";
      return `${header}${result.output}${footer}`;
    }
    if (toolName === "kirograph_gain") {
      const projectRoot = args.projectPath || process.cwd();
      const period = args.period ?? "session";
      const tracker = new import_tracker.TokenTracker(projectRoot);
      const stats = tracker.getStats(period);
      if (stats.totalCommands === 0) {
        return "No savings recorded yet. Use kirograph tools and kirograph_exec \u2014 savings are tracked automatically.";
      }
      const lines = [
        `Token Savings (${period}):`,
        `  Total calls: ${stats.totalCommands}`,
        `  Tokens without KiroGraph: ~${stats.totalOriginal.toLocaleString()}`,
        `  Tokens with KiroGraph:    ~${stats.totalCompressed.toLocaleString()}`,
        `  Saved: ${stats.totalSaved.toLocaleString()} tokens (${stats.savingsPercent}%)`
      ];
      if (stats.bySource.exec.count > 0 || stats.bySource.graph.count > 0 || stats.bySource.memory.count > 0 || stats.bySource.docs.count > 0) {
        lines.push("", "By source:");
        if (stats.bySource.graph.count > 0) {
          lines.push(`  Graph tools: ${stats.bySource.graph.count} calls, ~${stats.bySource.graph.saved.toLocaleString()} tokens saved (vs file reads/grep)`);
        }
        if (stats.bySource.docs.count > 0) {
          lines.push(`  Docs tools: ${stats.bySource.docs.count} calls, ~${stats.bySource.docs.saved.toLocaleString()} tokens saved (vs reading full doc files)`);
        }
        if (stats.bySource.exec.count > 0) {
          lines.push(`  Compression: ${stats.bySource.exec.count} calls, ~${stats.bySource.exec.saved.toLocaleString()} tokens saved (vs raw output)`);
        }
        if (stats.bySource.memory.count > 0) {
          lines.push(`  Memory: ${stats.bySource.memory.count} calls, ~${stats.bySource.memory.saved.toLocaleString()} tokens saved (vs re-discovering context)`);
        }
      }
      if (Object.keys(stats.byFamily).length > 0) {
        lines.push("", "Top families:");
        for (const [family, data] of Object.entries(stats.byFamily).slice(0, 7)) {
          lines.push(`  ${family}: ${data.count} calls, ${data.savings}% avg savings`);
        }
      }
      if (stats.recentCommands.length > 0) {
        lines.push("", "Recent:");
        for (const cmd of stats.recentCommands.slice(0, 5)) {
          const tag = cmd.source === "graph" ? "\u{1F4CA}" : "\u26A1";
          lines.push(`  ${tag} ${cmd.command.slice(0, 40)} \u2192 ${cmd.savings}% saved`);
        }
      }
      return lines.join("\n");
    }
    const cg = await this.getConnection(args.projectPath);
    if (!cg) return "KiroGraph not initialized. Run `kirograph init` in your project first.";
    writeSessionMarker(cg.getProjectRoot());
    switch (toolName) {
      case "kirograph_search": {
        const limit = clampLimit(args.limit, 10);
        const results = cg.searchNodes(
          args.query,
          args.kind,
          limit
        );
        if (results.length === 0) return `No symbols found matching "${args.query}".`;
        return results.map(
          (r) => `${mapKind(r.node.kind)} ${r.node.name}
  File: ${r.node.filePath}:${r.node.startLine}
  Qualified: ${r.node.qualifiedName}`
        ).join("\n\n");
      }
      case "kirograph_context": {
        const ctx = await cg.buildContext(args.task, {
          maxNodes: args.maxNodes ?? 20,
          includeCode: args.includeCode ?? true
        });
        const lines = [ctx.summary, ""];
        if (ctx.entryPoints.length === 0) {
          lines.push("No matching symbols found. If this is a new feature, consider using kirograph_files to explore the codebase structure.");
        } else {
          lines.push("## Entry Points");
          for (const n of ctx.entryPoints) {
            lines.push(`- ${mapKind(n.kind)} \`${n.name}\` \u2014 ${n.filePath}:${n.startLine}`);
            if (ctx.codeSnippets.has(n.id)) {
              lines.push("```", ctx.codeSnippets.get(n.id), "```");
            }
          }
          if (ctx.relatedNodes.length > 0) {
            lines.push("", "## Related Symbols");
            for (const n of ctx.relatedNodes.slice(0, 10)) {
              lines.push(`- ${mapKind(n.kind)} \`${n.name}\` \u2014 ${n.filePath}:${n.startLine}`);
            }
          }
        }
        try {
          const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
          const projectRoot = cg.getProjectRoot();
          const config = await loadConfig(projectRoot);
          if (config.enableMemory) {
            const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
            const db = cg.getDatabase();
            db.applyMemorySchema();
            const mem = new MemoryManager(config, db.getRawDb());
            mem.initialize();
            const qualifiedNames = [
              ...ctx.entryPoints.map((n) => n.qualifiedName),
              ...ctx.relatedNodes.slice(0, 5).map((n) => n.qualifiedName)
            ].filter(Boolean);
            const contextLimit = config.memoryContextLimit ?? 3;
            const contextThreshold = config.memoryContextThreshold ?? 0.3;
            let memResults = mem.getLinkedObservations(qualifiedNames, contextLimit, contextThreshold);
            if (memResults.length === 0) {
              memResults = (await mem.search(args.task, { limit: contextLimit })).filter((r) => r.score >= contextThreshold);
            }
            if (memResults.length > 0) {
              lines.push("", "## Related Memory");
              for (const r of memResults.slice(0, contextLimit)) {
                const age = formatAge(r.observation.createdAt);
                lines.push(`- [${r.observation.kind}] ${r.observation.content} (${age})`);
              }
            }
          }
        } catch {
        }
        try {
          const projectRoot2 = cg.getProjectRoot();
          const config2 = await (await Promise.resolve().then(() => require("../config.js"))).loadConfig(projectRoot2);
          if (config2.enableDocs && config2.docsContextLimit > 0) {
            const db2 = cg.getDatabase();
            db2.applyDocsSchema();
            const { DocsQueries } = await Promise.resolve().then(() => require("../docs/queries.js"));
            const docsQueries = new DocsQueries(db2.getRawDb(), projectRoot2);
            const qNames = ctx.entryPoints.map((n) => n.qualifiedName).filter(Boolean);
            if (qNames.length > 0) {
              const docRefs = docsQueries.getRefs({ qualifiedName: qNames[0] });
              const additionalRefs = qNames.slice(1, 5).flatMap((qn) => docsQueries.getRefs({ qualifiedName: qn }));
              const allDocRefs = [...docRefs, ...additionalRefs];
              const seenSections = /* @__PURE__ */ new Set();
              const uniqueRefs = allDocRefs.filter((r) => {
                if (seenSections.has(r.sectionId)) return false;
                seenSections.add(r.sectionId);
                return r.confidence >= config2.docsContextThreshold;
              }).slice(0, config2.docsContextLimit);
              if (uniqueRefs.length > 0) {
                lines.push("", "## Related Documentation");
                for (const ref of uniqueRefs) {
                  const section = docsQueries.getSection(ref.sectionId);
                  if (section) {
                    const summary = section.section.summary ?? section.section.title;
                    lines.push(`- [${ref.refType}] ${summary} \u2014 ${section.section.filePath} (ID: ${ref.sectionId})`);
                  }
                }
              }
            }
          }
        } catch {
        }
        return lines.join("\n");
      }
      case "kirograph_callers": {
        const limit = clampLimit(args.limit, 20);
        const results = cg.searchNodes(args.symbol, void 0, 5);
        if (results.length === 0) return `Symbol "${args.symbol}" not found in index.`;
        const node = results[0].node;
        const callers = await cg.getCallers(node.id, limit);
        if (callers.length === 0) return `No callers found for \`${node.name}\`.`;
        return `Callers of \`${node.name}\`:
` + callers.map(
          (n) => `- ${mapKind(n.kind)} \`${n.name}\` \u2014 ${n.filePath}:${n.startLine}`
        ).join("\n");
      }
      case "kirograph_callees": {
        const limit = clampLimit(args.limit, 20);
        const results = cg.searchNodes(args.symbol, void 0, 5);
        if (results.length === 0) return `Symbol "${args.symbol}" not found in index.`;
        const node = results[0].node;
        const callees = await cg.getCallees(node.id, limit);
        if (callees.length === 0) return `\`${node.name}\` doesn't call any indexed symbols.`;
        return `\`${node.name}\` calls:
` + callees.map(
          (n) => `- ${mapKind(n.kind)} \`${n.name}\` \u2014 ${n.filePath}:${n.startLine}`
        ).join("\n");
      }
      case "kirograph_impact": {
        const results = cg.searchNodes(args.symbol, void 0, 5);
        if (results.length === 0) return `Symbol "${args.symbol}" not found in index.`;
        const node = results[0].node;
        const affected = await cg.getImpactRadius(node.id, args.depth ?? 2);
        if (affected.length === 0) return `No dependents found for \`${node.name}\`.`;
        let output = `Changing \`${node.name}\` may affect ${affected.length} symbol(s):
` + affected.map((n) => `- ${mapKind(n.kind)} \`${n.name}\` \u2014 ${n.filePath}:${n.startLine}`).join("\n");
        try {
          const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
          const projectRoot = cg.getProjectRoot();
          const config = await loadConfig(projectRoot);
          if (config.enableMemory) {
            const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
            const db = cg.getDatabase();
            db.applyMemorySchema();
            const mem = new MemoryManager(config, db.getRawDb());
            mem.initialize();
            const contextLimit = config.memoryContextLimit ?? 3;
            const contextThreshold = config.memoryContextThreshold ?? 0.3;
            const memResults = mem.getLinkedObservations(
              [node.qualifiedName],
              contextLimit,
              contextThreshold
            );
            if (memResults.length > 0) {
              output += "\n\nRelated Memory:";
              for (const r of memResults) {
                const age = formatAge(r.observation.createdAt);
                output += `
- [${r.observation.kind}] ${r.observation.content} (${age})`;
              }
            }
          }
        } catch {
        }
        return output;
      }
      case "kirograph_node": {
        const results = cg.searchNodes(args.symbol, void 0, 5);
        if (results.length === 0) return `Symbol "${args.symbol}" not found in index.`;
        const node = results[0].node;
        const lines = [
          `${mapKind(node.kind)} \`${node.name}\``,
          `File: ${node.filePath}:${node.startLine}-${node.endLine}`,
          `Qualified: ${node.qualifiedName}`,
          node.signature ? `Signature: ${node.signature}` : "",
          node.docstring ? `Docs: ${node.docstring}` : ""
        ].filter(Boolean);
        if (args.includeCode) {
          const src = cg.getNodeSource(node);
          if (src) lines.push("", "```", src, "```");
        }
        return lines.join("\n");
      }
      case "kirograph_status": {
        const stats = await cg.getStats();
        const langLine = Object.entries(stats.filesByLanguage).sort((a, b) => b[1] - a[1]).map(([k, v]) => `${k}=${v}`).join(", ");
        const dbMb = (stats.dbSizeBytes / 1024 / 1024).toFixed(2);
        const semanticLines = stats.embeddingsEnabled ? [
          `  Semantic search: enabled`,
          `  Semantic model:  ${stats.embeddingModel}`,
          `  Semantic engine: ${stats.semanticEngine === "sqlite-vec" ? `sqlite-vec (${stats.vecIndexCount} entries in ANN index)` : stats.semanticEngine === "orama" ? `orama hybrid (${stats.vecIndexCount} docs in index)` : stats.semanticEngine === "pglite" ? `pglite+pgvector (${stats.vecIndexCount} rows in DB)` : stats.semanticEngine === "lancedb" ? `lancedb (${stats.vecIndexCount} entries in ANN index)` : stats.semanticEngine === "qdrant" ? `qdrant (${stats.vecIndexCount} points in collection)` : stats.semanticEngine === "typesense" ? `typesense (${stats.vecIndexCount} documents in collection)` : "in-process cosine"}`,
          `  Embeddings:      ${stats.embeddingCount} / ${stats.embeddableNodeCount || stats.nodes} embeddable symbols`,
          ...stats.engineFallback ? [`  \u26A0 Engine fallback: ${stats.engineFallback}`] : []
        ] : [`  Semantic search: disabled`];
        const frameworkLine = stats.frameworks.length > 0 ? `  Frameworks: ${stats.frameworks.join(", ")}` : `  Frameworks: none detected`;
        const archLine = stats.architectureEnabled ? stats.architectureStats ? `  Architecture: enabled \u2014 ${stats.architectureStats.packages} packages, ${stats.architectureStats.layers} layers, ${stats.architectureStats.packageDeps} deps` : `  Architecture: enabled (not yet analyzed \u2014 run kirograph index)` : `  Architecture: disabled`;
        let docsLine = "  Documentation: disabled";
        try {
          const { loadConfig: loadCfg } = await Promise.resolve().then(() => require("../config.js"));
          const cfg = await loadCfg(cg.getProjectRoot());
          if (cfg.enableDocs) {
            const db = cg.getDatabase();
            db.applyDocsSchema();
            const rawDb = db.getRawDb();
            const docFiles = rawDb.get("SELECT COUNT(DISTINCT file_path) as cnt FROM doc_sections")?.cnt ?? 0;
            const docSections = rawDb.get("SELECT COUNT(*) as cnt FROM doc_sections")?.cnt ?? 0;
            const docRefs = rawDb.get("SELECT COUNT(*) as cnt FROM doc_code_refs")?.cnt ?? 0;
            docsLine = `  Documentation: enabled \u2014 ${docFiles} files, ${docSections} sections, ${docRefs} code refs`;
          }
        } catch {
        }
        const threshold = stats.syncWarningThreshold ?? 10;
        const pendingFiles = stats.pendingFiles ?? 0;
        const syncRunning = stats.syncRunning ?? false;
        const syncLines = [];
        if (syncRunning) {
          syncLines.push(`  \u26A0 Sync is currently running in the background.`);
        }
        if (threshold > 0 && pendingFiles >= threshold) {
          syncLines.push(
            `  \u26A0 Index may be incomplete \u2014 ${pendingFiles} file${pendingFiles !== 1 ? "s" : ""} pending sync.` + (syncRunning ? " Sync is running in background." : " Run `kirograph sync` to update.") + ` Would you like to wait before proceeding?`
          );
        }
        const tracker = new import_tracker.TokenTracker(cg.getProjectRoot());
        const gainStats = tracker.getStats("session");
        const gainLines = [];
        if (gainStats.totalCommands > 0) {
          gainLines.push(`  Compression: ${gainStats.totalCommands} commands, ${gainStats.savingsPercent}% avg savings (${gainStats.totalSaved.toLocaleString()} tokens saved this session)`);
        }
        return [
          `KiroGraph Status`,
          `  Project: ${cg.getProjectRoot()}`,
          `  Files indexed: ${stats.files}`,
          `  Symbols: ${stats.nodes}`,
          `  Relationships: ${stats.edges}`,
          `  By kind: ${Object.entries(stats.nodesByKind).map(([k, v]) => `${k}=${v}`).join(", ")}`,
          langLine ? `  By language: ${langLine}` : "",
          frameworkLine,
          archLine,
          docsLine,
          `  DB size: ${dbMb} MB`,
          ...semanticLines,
          ...syncLines,
          ...gainLines
        ].filter(Boolean).join("\n");
      }
      case "kirograph_files": {
        let renderTree2 = function(nodes, prefix) {
          for (let i = 0; i < nodes.length; i++) {
            const node = nodes[i];
            const isLast = i === nodes.length - 1;
            const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
            const childPrefix = prefix + (isLast ? "    " : "\u2502   ");
            const meta = includeMetadata && node.type === "file" && node.language ? `  [${node.language}${node.symbolCount ? ` \xB7 ${node.symbolCount} symbols` : ""}]` : "";
            lines.push(`${prefix}${connector}${node.name}${meta}`);
            if (node.children?.length) renderTree2(node.children, childPrefix);
          }
        };
        var renderTree = renderTree2;
        const format = args.format ?? "tree";
        const includeMetadata = args.includeMetadata !== false;
        const tree = cg.getFiles({
          filterPath: args.filterPath,
          pattern: args.pattern,
          maxDepth: args.maxDepth
        });
        if (format === "flat") {
          let flattenTree2 = function(nodes) {
            for (const node of nodes) {
              if (node.type === "file") {
                const meta = includeMetadata && node.language ? ` [${node.language}${node.symbolCount ? ` \xB7 ${node.symbolCount}` : ""}]` : "";
                flat.push(`${node.path}${meta}`);
              }
              if (node.children?.length) flattenTree2(node.children);
            }
          };
          var flattenTree = flattenTree2;
          const flat = [];
          flattenTree2(tree);
          return flat.length > 0 ? flat.join("\n") : "No indexed files found.";
        }
        if (format === "grouped") {
          let groupTree2 = function(nodes) {
            for (const node of nodes) {
              if (node.type === "file") {
                const dir = node.path.includes("/") ? node.path.slice(0, node.path.lastIndexOf("/")) : ".";
                if (!groups.has(dir)) groups.set(dir, []);
                groups.get(dir).push(node);
              }
              if (node.children?.length) groupTree2(node.children);
            }
          };
          var groupTree = groupTree2;
          const groups = /* @__PURE__ */ new Map();
          groupTree2(tree);
          const lines2 = [];
          for (const [dir, files] of [...groups.entries()].sort()) {
            lines2.push(`${dir}/`);
            for (const f of files) {
              const meta = includeMetadata && f.language ? ` [${f.language}${f.symbolCount ? ` \xB7 ${f.symbolCount}` : ""}]` : "";
              lines2.push(`  ${f.name}${meta}`);
            }
          }
          return lines2.length > 0 ? lines2.join("\n") : "No indexed files found.";
        }
        if (format === "compact") {
          let compactTree2 = function(nodes) {
            for (const node of nodes) {
              if (node.type === "file") {
                const dir = node.path.includes("/") ? node.path.slice(0, node.path.lastIndexOf("/")) : ".";
                const stat = dirStats.get(dir) || { files: 0, symbols: 0, langs: /* @__PURE__ */ new Map() };
                stat.files++;
                stat.symbols += node.symbolCount || 0;
                if (node.language) stat.langs.set(node.language, (stat.langs.get(node.language) || 0) + 1);
                dirStats.set(dir, stat);
              }
              if (node.children?.length) compactTree2(node.children);
            }
          };
          var compactTree = compactTree2;
          const dirStats = /* @__PURE__ */ new Map();
          compactTree2(tree);
          const totalFiles = [...dirStats.values()].reduce((s, d) => s + d.files, 0);
          const totalSymbols = [...dirStats.values()].reduce((s, d) => s + d.symbols, 0);
          const lines2 = [`${totalFiles} files, ${totalSymbols} symbols in ${dirStats.size} directories:
`];
          for (const [dir, stat] of [...dirStats.entries()].sort()) {
            const langSummary = [...stat.langs.entries()].map(([l, c]) => `${l}:${c}`).join(" ");
            lines2.push(`${dir}/ (${stat.files} files, ${stat.symbols} symbols) ${langSummary}`);
          }
          return lines2.join("\n");
        }
        const lines = [];
        renderTree2(tree, "");
        return lines.length > 0 ? lines.join("\n") : "No indexed files found.";
      }
      case "kirograph_dead_code": {
        const limit = clampLimit(args.limit, 50);
        const dead = cg.findDeadCode(limit);
        if (dead.length === 0) return "No dead code detected.";
        return `Potential dead code (${dead.length} unexported symbols with no incoming references):
` + dead.map((n) => `- ${mapKind(n.kind)} \`${n.name}\` \u2014 ${n.filePath}:${n.startLine}`).join("\n");
      }
      case "kirograph_circular_deps": {
        const cycles = cg.findCircularDependencies();
        if (cycles.length === 0) return "No circular dependencies found.";
        return `Found ${cycles.length} circular dependency cycle(s):
` + cycles.map((cycle, i) => `Cycle ${i + 1}: ${cycle.join(" \u2192 ")}`).join("\n");
      }
      case "kirograph_path": {
        const fromResults = cg.searchNodes(args.from, void 0, 3);
        const toResults = cg.searchNodes(args.to, void 0, 3);
        if (fromResults.length === 0) return `Symbol "${args.from}" not found in index.`;
        if (toResults.length === 0) return `Symbol "${args.to}" not found in index.`;
        const fromNode = fromResults[0].node;
        const toNode = toResults[0].node;
        const pathNodes = await cg.findPath(fromNode.id, toNode.id);
        if (pathNodes.length === 0) return `No path found between \`${fromNode.name}\` and \`${toNode.name}\`.`;
        return `Path from \`${fromNode.name}\` to \`${toNode.name}\` (${pathNodes.length} nodes):
` + pathNodes.map((n, i) => `${i + 1}. ${mapKind(n.kind)} \`${n.name}\` \u2014 ${n.filePath}:${n.startLine}`).join("\n");
      }
      case "kirograph_type_hierarchy": {
        const results = cg.searchNodes(args.symbol, void 0, 5);
        if (results.length === 0) return `Symbol "${args.symbol}" not found in index.`;
        const node = results[0].node;
        const direction = args.direction ?? "both";
        const hierarchy = cg.getTypeHierarchy(node.id, direction);
        if (hierarchy.length === 0) return `No type hierarchy found for \`${node.name}\`.`;
        return `Type hierarchy for \`${node.name}\` (direction: ${direction}):
` + hierarchy.map((n) => `- ${mapKind(n.kind)} \`${n.name}\` \u2014 ${n.filePath}:${n.startLine}`).join("\n");
      }
      case "kirograph_architecture": {
        if (!cg.isArchitectureEnabled()) {
          return "Architecture analysis is disabled. Set enableArchitecture=true in .kirograph/config.json and re-index.";
        }
        const level = args.level ?? "both";
        const includeFiles = args.includeFiles === true;
        const arch = cg.getArchitecture();
        const lines = ["# Architecture"];
        if ((level === "packages" || level === "both") && arch.packages.length > 0) {
          lines.push("\n## Packages");
          for (const pkg of arch.packages) {
            const meta = [pkg.language, pkg.version].filter(Boolean).join(", ");
            lines.push(`- **${pkg.name}** (${pkg.path}) [${pkg.source}${meta ? " \xB7 " + meta : ""}]`);
          }
          if (arch.packageDeps.length > 0) {
            lines.push("\n## Package Dependencies");
            for (const dep of arch.packageDeps) {
              const src = arch.packages.find((p) => p.id === dep.sourcePkg)?.name ?? dep.sourcePkg;
              const tgt = arch.packages.find((p) => p.id === dep.targetPkg)?.name ?? dep.targetPkg;
              lines.push(`- ${src} \u2192 ${tgt} (${dep.depCount} import${dep.depCount !== 1 ? "s" : ""})`);
            }
          }
        }
        if ((level === "layers" || level === "both") && arch.layers.length > 0) {
          lines.push("\n## Layers");
          for (const layer of arch.layers) {
            const fileCount = Object.values(arch.fileLayers).filter((fl) => fl.some((l) => l.layerId === layer.id)).length;
            lines.push(`- **${layer.name}** [${layer.source}] \u2014 ${fileCount} file${fileCount !== 1 ? "s" : ""}`);
          }
          if (arch.layerDeps.length > 0) {
            lines.push("\n## Layer Dependencies");
            for (const dep of arch.layerDeps) {
              const src = dep.sourceLayer.replace("layer:", "");
              const tgt = dep.targetLayer.replace("layer:", "");
              lines.push(`- ${src} \u2192 ${tgt} (${dep.depCount})`);
            }
          }
        }
        if (includeFiles && (level === "packages" || level === "both")) {
          lines.push("\n## File \u2192 Package");
          for (const [file, pkgIds] of Object.entries(arch.filePackages).slice(0, 50)) {
            const names = pkgIds.map((id) => arch.packages.find((p) => p.id === id)?.name ?? id).join(", ");
            lines.push(`- ${file}: ${names}`);
          }
          if (Object.keys(arch.filePackages).length > 50) lines.push("  \u2026(truncated)");
        }
        if (arch.packages.length === 0 && arch.layers.length === 0) {
          return "No architecture data found. Run `kirograph index` with enableArchitecture=true.";
        }
        return lines.join("\n");
      }
      case "kirograph_coupling": {
        if (!cg.isArchitectureEnabled()) {
          return "Architecture analysis is disabled. Set enableArchitecture=true in .kirograph/config.json and re-index.";
        }
        const sortBy = args.sortBy ?? "instability";
        const limit = clampLimit(args.limit, 20);
        const arch = cg.getArchitecture();
        if (arch.coupling.length === 0) {
          return "No coupling data. Run `kirograph index` with enableArchitecture=true.";
        }
        const sorted = [...arch.coupling].sort((a, b) => {
          if (sortBy === "afferent") return b.afferent - a.afferent;
          if (sortBy === "efferent") return b.efferent - a.efferent;
          return b.instability - a.instability;
        }).slice(0, limit);
        const lines = [
          `Coupling Metrics (sorted by ${sortBy}):`,
          "",
          "Package                          Ca    Ce    I",
          "\u2500".repeat(52)
        ];
        for (const c of sorted) {
          const pkg = arch.packages.find((p) => p.id === c.packageId);
          const name = (pkg?.name ?? c.packageId).slice(0, 32).padEnd(32);
          const ca = String(c.afferent).padStart(4);
          const ce = String(c.efferent).padStart(4);
          const inst = c.instability.toFixed(2).padStart(5);
          lines.push(`${name}  ${ca}  ${ce}  ${inst}`);
        }
        lines.push("", "Ca=afferent (depended on by), Ce=efferent (depends on), I=instability (Ce/(Ca+Ce))");
        return lines.join("\n");
      }
      case "kirograph_package": {
        if (!cg.isArchitectureEnabled()) {
          return "Architecture analysis is disabled. Set enableArchitecture=true in .kirograph/config.json and re-index.";
        }
        const query = args.package.toLowerCase();
        const includeFiles = args.includeFiles !== false;
        const arch = cg.getArchitecture();
        const pkg = arch.packages.find(
          (p) => p.name.toLowerCase().includes(query) || p.path.toLowerCase().includes(query) || p.id.toLowerCase().includes(query)
        );
        if (!pkg) return `Package "${args.package}" not found. Use kirograph_architecture to list all packages.`;
        const lines = [
          `## Package: ${pkg.name}`,
          `Path: ${pkg.path}`,
          `Source: ${pkg.source}${pkg.manifestPath ? ` (${pkg.manifestPath})` : ""}`,
          ...pkg.version ? [`Version: ${pkg.version}`] : [],
          ...pkg.language ? [`Language: ${pkg.language}`] : []
        ];
        const deps = arch.packageDeps.filter((d) => d.sourcePkg === pkg.id);
        const dependents = arch.packageDeps.filter((d) => d.targetPkg === pkg.id);
        const coupling = arch.coupling.find((c) => c.packageId === pkg.id);
        if (coupling) {
          lines.push("", `Coupling: Ca=${coupling.afferent} Ce=${coupling.efferent} I=${coupling.instability.toFixed(2)}`);
        }
        if (deps.length > 0) {
          lines.push("", `Depends on (${deps.length}):`);
          for (const dep of deps) {
            const name = arch.packages.find((p) => p.id === dep.targetPkg)?.name ?? dep.targetPkg;
            lines.push(`  \u2192 ${name} (${dep.depCount} import${dep.depCount !== 1 ? "s" : ""})`);
          }
        }
        if (dependents.length > 0) {
          lines.push("", `Depended on by (${dependents.length}):`);
          for (const dep of dependents) {
            const name = arch.packages.find((p) => p.id === dep.sourcePkg)?.name ?? dep.sourcePkg;
            lines.push(`  \u2190 ${name} (${dep.depCount} import${dep.depCount !== 1 ? "s" : ""})`);
          }
        }
        if (pkg.externalDeps && pkg.externalDeps.length > 0) {
          lines.push("", `External deps (${pkg.externalDeps.length}): ${pkg.externalDeps.slice(0, 10).join(", ")}${pkg.externalDeps.length > 10 ? "\u2026" : ""}`);
        }
        if (includeFiles) {
          const files = Object.entries(arch.filePackages).filter(([, ids]) => ids.includes(pkg.id)).map(([f]) => f).sort();
          if (files.length > 0) {
            lines.push("", `Files (${files.length}):`);
            for (const f of files.slice(0, 30)) lines.push(`  ${f}`);
            if (files.length > 30) lines.push(`  \u2026and ${files.length - 30} more`);
          }
        }
        return lines.join("\n");
      }
      case "kirograph_hotspots": {
        const limit = clampLimit(args.limit, 20);
        const hotspots = cg.findHotspots(limit);
        if (hotspots.length === 0) return "No symbols found in index.";
        const lines = [`Top ${hotspots.length} most-connected symbols (by edge degree):
`];
        for (const n of hotspots) {
          lines.push(`${mapKind(n.kind)} \`${n.name}\` \u2014 degree ${n.degree} (in: ${n.inDegree}, out: ${n.outDegree})`);
          lines.push(`  File: ${n.filePath}:${n.startLine}`);
        }
        return lines.join("\n");
      }
      case "kirograph_surprising": {
        const limit = clampLimit(args.limit, 20);
        const connections = cg.findSurprisingConnections(limit);
        if (connections.length === 0) return "No surprising cross-file connections found.";
        const lines = [`Top ${connections.length} surprising cross-file connections:
`];
        for (const c of connections) {
          lines.push(`${mapKind(c.source.kind)} \`${c.source.name}\` ${c.kind}\u2192 ${mapKind(c.target.kind)} \`${c.target.name}\` (score: ${c.score.toFixed(2)})`);
          lines.push(`  ${c.source.filePath} \u2192 ${c.target.filePath}`);
        }
        return lines.join("\n");
      }
      case "kirograph_diff": {
        const sm = cg.createSnapshotManager();
        const snapshot = args.snapshot ? sm.load(args.snapshot) : sm.loadLatest();
        if (!snapshot) {
          return args.snapshot ? `Snapshot "${args.snapshot}" not found. Use \`kirograph snapshot list\` to see available snapshots.` : "No snapshots found. Run `kirograph snapshot` to save one first.";
        }
        const diff = sm.diff(snapshot, sm.currentSnapshot());
        const fromDate = new Date(diff.from.timestamp).toISOString().slice(0, 19).replace("T", " ");
        const lines = [
          `Graph diff: "${diff.from.label}" (${fromDate}) \u2192 current`,
          ``,
          `Symbols: +${diff.addedNodes.length} added, -${diff.removedNodes.length} removed`,
          `Edges:   +${diff.addedEdges.length} added, -${diff.removedEdges.length} removed`
        ];
        if (diff.addedNodes.length > 0) {
          lines.push(`
## Added symbols (${diff.addedNodes.length})`);
          for (const n of diff.addedNodes.slice(0, 30)) {
            lines.push(`+ ${mapKind(n.kind)} \`${n.name}\` \u2014 ${n.filePath}`);
          }
          if (diff.addedNodes.length > 30) lines.push(`  \u2026and ${diff.addedNodes.length - 30} more`);
        }
        if (diff.removedNodes.length > 0) {
          lines.push(`
## Removed symbols (${diff.removedNodes.length})`);
          for (const n of diff.removedNodes.slice(0, 30)) {
            lines.push(`- ${mapKind(n.kind)} \`${n.name}\` \u2014 ${n.filePath}`);
          }
          if (diff.removedNodes.length > 30) lines.push(`  \u2026and ${diff.removedNodes.length - 30} more`);
        }
        return lines.join("\n");
      }
      // ── Memory tools ────────────────────────────────────────────────────────
      case "kirograph_mem_search": {
        const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
        const projectRoot = cg.getProjectRoot();
        const config = await loadConfig(projectRoot);
        if (!config.enableMemory) return "Memory is not enabled. Set enableMemory: true in .kirograph/config.json";
        const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
        const db = cg.getDatabase();
        db.applyMemorySchema();
        const mem = new MemoryManager(config, db.getRawDb());
        mem.initialize();
        const results = await mem.search(args.query, {
          limit: args.limit ?? 10,
          kind: args.kind,
          sessionId: args.sessionId
        });
        if (results.length === 0) return `No memory observations found for "${args.query}".`;
        return results.map((r, i) => {
          const age = formatAge(r.observation.createdAt);
          return `${i + 1}. [${r.observation.kind}] ${r.observation.content} (${age})`;
        }).join("\n");
      }
      case "kirograph_mem_store": {
        const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
        const projectRoot = cg.getProjectRoot();
        const config = await loadConfig(projectRoot);
        if (!config.enableMemory) return "Memory is not enabled. Set enableMemory: true in .kirograph/config.json";
        const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
        const db = cg.getDatabase();
        db.applyMemorySchema();
        const mem = new MemoryManager(config, db.getRawDb());
        mem.initialize();
        const id = await mem.store({
          content: args.content,
          kind: args.kind ?? "note",
          source: "agent"
        });
        if (!id) return "Observation already exists (duplicate content).";
        return `Stored observation ${id} [${args.kind ?? "note"}]`;
      }
      case "kirograph_mem_timeline": {
        const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
        const projectRoot = cg.getProjectRoot();
        const config = await loadConfig(projectRoot);
        if (!config.enableMemory) return "Memory is not enabled. Set enableMemory: true in .kirograph/config.json";
        const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
        const db = cg.getDatabase();
        db.applyMemorySchema();
        const mem = new MemoryManager(config, db.getRawDb());
        mem.initialize();
        const { sessions, observations } = mem.timeline({
          limit: args.limit ?? 5,
          sessionId: args.sessionId
        });
        if (sessions.length === 0) return "No memory sessions found.";
        const lines = [];
        for (const session of sessions) {
          const start = new Date(session.startedAt).toISOString().slice(0, 16).replace("T", " ");
          const status = session.endedAt ? "ended" : "active";
          const obs = observations.get(session.id) ?? [];
          lines.push(`## ${start} [${session.ide ?? "unknown"}] (${status}, ${obs.length} observations)`);
          for (const o of obs.slice(0, 5)) {
            lines.push(`  - [${o.kind}] ${o.content.slice(0, 120)}`);
          }
          if (obs.length > 5) lines.push(`  \u2026and ${obs.length - 5} more`);
        }
        return lines.join("\n");
      }
      case "kirograph_mem_status": {
        const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
        const projectRoot = cg.getProjectRoot();
        const config = await loadConfig(projectRoot);
        if (!config.enableMemory) return "Memory is not enabled. Set enableMemory: true in .kirograph/config.json";
        const { MemoryManager } = await Promise.resolve().then(() => require("../memory/index.js"));
        const db = cg.getDatabase();
        db.applyMemorySchema();
        const mem = new MemoryManager(config, db.getRawDb());
        mem.initialize();
        const stats = mem.getStats();
        const lines = [
          "KiroGraph Memory Status",
          `  Sessions: ${stats.sessions} (${stats.activeSessions} active)`,
          `  Observations: ${stats.observations}`,
          `  Symbol links: ${stats.links}`,
          `  Embeddings: ${stats.vectors} / ${stats.embeddableCount}`,
          `  Model mismatch: ${stats.modelMismatch ? "\u26A0 yes \u2014 run kirograph mem reembed" : "no"}`,
          `  Caveman compression: ${config.cavemanMode !== "off" ? config.cavemanMode : "off (storing raw)"}`
        ];
        return lines.join("\n");
      }
      // ── Docs tools ────────────────────────────────────────────────────────────
      case "kirograph_docs_toc": {
        const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
        const projectRoot = cg.getProjectRoot();
        const config = await loadConfig(projectRoot);
        if (!config.enableDocs) return "Documentation indexing is not enabled. Set enableDocs: true in .kirograph/config.json and run kirograph index.";
        const { DocsQueries } = await Promise.resolve().then(() => require("../docs/queries.js"));
        const db = cg.getDatabase();
        db.applyDocsSchema();
        const docs = new DocsQueries(db.getRawDb(), projectRoot);
        const toc = docs.getToc({ file: args.file, tree: args.tree });
        if (toc.length === 0) return args.file ? `No sections found in "${args.file}".` : "No documentation indexed. Run kirograph index.";
        const lines = [];
        const renderEntry = (entry, indent) => {
          const prefix = "#".repeat(entry.level || 1);
          const summary = entry.summary ? ` \u2014 ${entry.summary}` : "";
          lines.push(`${indent}${prefix} ${entry.title}${summary}`);
          lines.push(`${indent}  ID: ${entry.id}`);
          if (entry.children?.length) {
            for (const child of entry.children) renderEntry(child, indent + "  ");
          }
        };
        if (args.tree) {
          for (const entry of toc) renderEntry(entry, "");
        } else {
          for (const entry of toc) {
            const prefix = "#".repeat(entry.level || 1);
            const summary = entry.summary ? ` \u2014 ${entry.summary}` : "";
            lines.push(`${prefix} ${entry.title} [${entry.filePath}]${summary}`);
            lines.push(`  ID: ${entry.id}`);
          }
        }
        return lines.join("\n");
      }
      case "kirograph_docs_search": {
        const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
        const projectRoot = cg.getProjectRoot();
        const config = await loadConfig(projectRoot);
        if (!config.enableDocs) return "Documentation indexing is not enabled. Set enableDocs: true in .kirograph/config.json and run kirograph index.";
        const { DocsQueries } = await Promise.resolve().then(() => require("../docs/queries.js"));
        const db = cg.getDatabase();
        db.applyDocsSchema();
        const docs = new DocsQueries(db.getRawDb(), projectRoot, config);
        const results = await docs.searchSections(args.query, {
          file: args.file,
          limit: args.limit ?? 10
        });
        if (results.length === 0) return `No documentation sections found matching "${args.query}".`;
        return results.map((r, i) => {
          const summary = r.section.summary ? `
  ${r.section.summary}` : "";
          return `${i + 1}. ${r.section.title} [${r.section.filePath}]${summary}
  ID: ${r.section.id}`;
        }).join("\n\n");
      }
      case "kirograph_docs_section": {
        const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
        const projectRoot = cg.getProjectRoot();
        const config = await loadConfig(projectRoot);
        if (!config.enableDocs) return "Documentation indexing is not enabled. Set enableDocs: true in .kirograph/config.json and run kirograph index.";
        const { DocsQueries } = await Promise.resolve().then(() => require("../docs/queries.js"));
        const db = cg.getDatabase();
        db.applyDocsSchema();
        const docs = new DocsQueries(db.getRawDb(), projectRoot);
        const result = docs.getSection(args.id, { context: args.context });
        if (!result) return `Section "${args.id}" not found.`;
        const lines = [];
        if (result.ancestors?.length) {
          lines.push("Breadcrumb: " + result.ancestors.map((a) => a.title).join(" > ") + " > " + result.section.title);
          lines.push("");
        }
        lines.push(result.content);
        if (result.children?.length) {
          lines.push("", "## Child sections:");
          for (const child of result.children) {
            const summary = child.summary ? ` \u2014 ${child.summary}` : "";
            lines.push(`  - ${child.title}${summary} (ID: ${child.id})`);
          }
        }
        return lines.join("\n");
      }
      case "kirograph_docs_outline": {
        const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
        const projectRoot = cg.getProjectRoot();
        const config = await loadConfig(projectRoot);
        if (!config.enableDocs) return "Documentation indexing is not enabled. Set enableDocs: true in .kirograph/config.json and run kirograph index.";
        const { DocsQueries } = await Promise.resolve().then(() => require("../docs/queries.js"));
        const db = cg.getDatabase();
        db.applyDocsSchema();
        const docs = new DocsQueries(db.getRawDb(), projectRoot);
        const outline = docs.getOutline(args.file);
        if (outline.length === 0) return `No sections found in "${args.file}". Is the file indexed?`;
        const lines = [`Outline: ${args.file}`, ""];
        const renderOutline = (entries, indent) => {
          for (const entry of entries) {
            const summary = entry.summary ? ` \u2014 ${entry.summary}` : "";
            lines.push(`${indent}${"#".repeat(entry.level || 1)} ${entry.title}${summary}`);
            if (entry.children?.length) renderOutline(entry.children, indent + "  ");
          }
        };
        renderOutline(outline, "");
        return lines.join("\n");
      }
      case "kirograph_docs_refs": {
        const { loadConfig } = await Promise.resolve().then(() => require("../config.js"));
        const projectRoot = cg.getProjectRoot();
        const config = await loadConfig(projectRoot);
        if (!config.enableDocs) return "Documentation indexing is not enabled. Set enableDocs: true in .kirograph/config.json and run kirograph index.";
        const { DocsQueries } = await Promise.resolve().then(() => require("../docs/queries.js"));
        const db = cg.getDatabase();
        db.applyDocsSchema();
        const docs = new DocsQueries(db.getRawDb(), projectRoot);
        const refs = docs.getRefs({
          sectionId: args.sectionId,
          qualifiedName: args.nodeId
        });
        if (refs.length === 0) {
          if (args.sectionId) return `No code references found in section "${args.sectionId}".`;
          if (args.nodeId) return `No documentation sections reference "${args.nodeId}".`;
          return "Provide either sectionId or nodeId to look up cross-references.";
        }
        return refs.map((r) => {
          const direction = args.sectionId ? `\u2192 ${r.qualifiedName}` : `\u2190 ${r.sectionTitle ?? r.sectionId}`;
          return `[${r.refType}] ${direction} (confidence: ${r.confidence.toFixed(2)})`;
        }).join("\n");
      }
      default:
        return `Unknown tool: ${toolName}`;
    }
  }
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  KIROGRAPH_TOOL_NAMES,
  ToolHandler,
  tools
});
//# sourceMappingURL=tools.js.map
