#
tokens: 43197/50000 3/307 files (page 20/23)
lines: off (toggle) GitHub
raw markdown copy
This is page 20 of 23. Use http://codebase.md/tosin2013/documcp?lines=false&page={x} to view the full context.

# Directory Structure

```
├── .dockerignore
├── .eslintignore
├── .eslintrc.json
├── .github
│   ├── agents
│   │   ├── documcp-ast.md
│   │   ├── documcp-deploy.md
│   │   ├── documcp-memory.md
│   │   ├── documcp-test.md
│   │   └── documcp-tool.md
│   ├── copilot-instructions.md
│   ├── dependabot.yml
│   ├── ISSUE_TEMPLATE
│   │   ├── automated-changelog.md
│   │   ├── bug_report.md
│   │   ├── bug_report.yml
│   │   ├── documentation_issue.md
│   │   ├── feature_request.md
│   │   ├── feature_request.yml
│   │   ├── npm-publishing-fix.md
│   │   └── release_improvements.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── release-drafter.yml
│   └── workflows
│       ├── auto-merge.yml
│       ├── ci.yml
│       ├── codeql.yml
│       ├── dependency-review.yml
│       ├── deploy-docs.yml
│       ├── README.md
│       ├── release-drafter.yml
│       └── release.yml
├── .gitignore
├── .husky
│   ├── commit-msg
│   └── pre-commit
├── .linkcheck.config.json
├── .markdown-link-check.json
├── .nvmrc
├── .pre-commit-config.yaml
├── .versionrc.json
├── ARCHITECTURAL_CHANGES_SUMMARY.md
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── commitlint.config.js
├── CONTRIBUTING.md
├── docker-compose.docs.yml
├── Dockerfile.docs
├── docs
│   ├── .docusaurus
│   │   ├── docusaurus-plugin-content-docs
│   │   │   └── default
│   │   │       └── __mdx-loader-dependency.json
│   │   └── docusaurus-plugin-content-pages
│   │       └── default
│   │           └── __plugin.json
│   ├── adrs
│   │   ├── adr-0001-mcp-server-architecture.md
│   │   ├── adr-0002-repository-analysis-engine.md
│   │   ├── adr-0003-static-site-generator-recommendation-engine.md
│   │   ├── adr-0004-diataxis-framework-integration.md
│   │   ├── adr-0005-github-pages-deployment-automation.md
│   │   ├── adr-0006-mcp-tools-api-design.md
│   │   ├── adr-0007-mcp-prompts-and-resources-integration.md
│   │   ├── adr-0008-intelligent-content-population-engine.md
│   │   ├── adr-0009-content-accuracy-validation-framework.md
│   │   ├── adr-0010-mcp-resource-pattern-redesign.md
│   │   ├── adr-0011-ce-mcp-compatibility.md
│   │   ├── adr-0012-priority-scoring-system-for-documentation-drift.md
│   │   ├── adr-0013-release-pipeline-and-package-distribution.md
│   │   └── README.md
│   ├── api
│   │   ├── .nojekyll
│   │   ├── assets
│   │   │   ├── hierarchy.js
│   │   │   ├── highlight.css
│   │   │   ├── icons.js
│   │   │   ├── icons.svg
│   │   │   ├── main.js
│   │   │   ├── navigation.js
│   │   │   ├── search.js
│   │   │   └── style.css
│   │   ├── hierarchy.html
│   │   ├── index.html
│   │   ├── modules.html
│   │   └── variables
│   │       └── TOOLS.html
│   ├── assets
│   │   └── logo.svg
│   ├── CE-MCP-FINDINGS.md
│   ├── development
│   │   └── MCP_INSPECTOR_TESTING.md
│   ├── docusaurus.config.js
│   ├── explanation
│   │   ├── architecture.md
│   │   └── index.md
│   ├── guides
│   │   ├── link-validation.md
│   │   ├── playwright-integration.md
│   │   └── playwright-testing-workflow.md
│   ├── how-to
│   │   ├── analytics-setup.md
│   │   ├── change-watcher.md
│   │   ├── custom-domains.md
│   │   ├── documentation-freshness-tracking.md
│   │   ├── drift-priority-scoring.md
│   │   ├── github-pages-deployment.md
│   │   ├── index.md
│   │   ├── llm-integration.md
│   │   ├── local-testing.md
│   │   ├── performance-optimization.md
│   │   ├── prompting-guide.md
│   │   ├── repository-analysis.md
│   │   ├── seo-optimization.md
│   │   ├── site-monitoring.md
│   │   ├── troubleshooting.md
│   │   └── usage-examples.md
│   ├── index.md
│   ├── knowledge-graph.md
│   ├── package-lock.json
│   ├── package.json
│   ├── phase-2-intelligence.md
│   ├── reference
│   │   ├── api-overview.md
│   │   ├── cli.md
│   │   ├── configuration.md
│   │   ├── deploy-pages.md
│   │   ├── index.md
│   │   ├── mcp-tools.md
│   │   └── prompt-templates.md
│   ├── research
│   │   ├── cross-domain-integration
│   │   │   └── README.md
│   │   ├── domain-1-mcp-architecture
│   │   │   ├── index.md
│   │   │   └── mcp-performance-research.md
│   │   ├── domain-2-repository-analysis
│   │   │   └── README.md
│   │   ├── domain-3-ssg-recommendation
│   │   │   ├── index.md
│   │   │   └── ssg-performance-analysis.md
│   │   ├── domain-4-diataxis-integration
│   │   │   └── README.md
│   │   ├── domain-5-github-deployment
│   │   │   ├── github-pages-security-analysis.md
│   │   │   └── index.md
│   │   ├── domain-6-api-design
│   │   │   └── README.md
│   │   ├── README.md
│   │   ├── research-integration-summary-2025-01-14.md
│   │   ├── research-progress-template.md
│   │   └── research-questions-2025-01-14.md
│   ├── robots.txt
│   ├── sidebars.js
│   ├── sitemap.xml
│   ├── src
│   │   └── css
│   │       └── custom.css
│   └── tutorials
│       ├── development-setup.md
│       ├── environment-setup.md
│       ├── first-deployment.md
│       ├── getting-started.md
│       ├── index.md
│       ├── memory-workflows.md
│       └── user-onboarding.md
├── ISSUE_IMPLEMENTATION_SUMMARY.md
├── jest.config.js
├── LICENSE
├── Makefile
├── MCP_PHASE2_IMPLEMENTATION.md
├── mcp-config-example.json
├── mcp.json
├── package-lock.json
├── package.json
├── README.md
├── release.sh
├── scripts
│   └── check-package-structure.cjs
├── SECURITY.md
├── setup-precommit.sh
├── src
│   ├── benchmarks
│   │   └── performance.ts
│   ├── index.ts
│   ├── memory
│   │   ├── contextual-retrieval.ts
│   │   ├── deployment-analytics.ts
│   │   ├── enhanced-manager.ts
│   │   ├── export-import.ts
│   │   ├── freshness-kg-integration.ts
│   │   ├── index.ts
│   │   ├── integration.ts
│   │   ├── kg-code-integration.ts
│   │   ├── kg-health.ts
│   │   ├── kg-integration.ts
│   │   ├── kg-link-validator.ts
│   │   ├── kg-storage.ts
│   │   ├── knowledge-graph.ts
│   │   ├── learning.ts
│   │   ├── manager.ts
│   │   ├── multi-agent-sharing.ts
│   │   ├── pruning.ts
│   │   ├── schemas.ts
│   │   ├── storage.ts
│   │   ├── temporal-analysis.ts
│   │   ├── user-preferences.ts
│   │   └── visualization.ts
│   ├── prompts
│   │   └── technical-writer-prompts.ts
│   ├── scripts
│   │   └── benchmark.ts
│   ├── templates
│   │   └── playwright
│   │       ├── accessibility.spec.template.ts
│   │       ├── Dockerfile.template
│   │       ├── docs-e2e.workflow.template.yml
│   │       ├── link-validation.spec.template.ts
│   │       └── playwright.config.template.ts
│   ├── tools
│   │   ├── analyze-deployments.ts
│   │   ├── analyze-readme.ts
│   │   ├── analyze-repository.ts
│   │   ├── change-watcher.ts
│   │   ├── check-documentation-links.ts
│   │   ├── cleanup-agent-artifacts.ts
│   │   ├── deploy-pages.ts
│   │   ├── detect-gaps.ts
│   │   ├── evaluate-readme-health.ts
│   │   ├── generate-config.ts
│   │   ├── generate-contextual-content.ts
│   │   ├── generate-llm-context.ts
│   │   ├── generate-readme-template.ts
│   │   ├── generate-technical-writer-prompts.ts
│   │   ├── kg-health-check.ts
│   │   ├── manage-preferences.ts
│   │   ├── manage-sitemap.ts
│   │   ├── optimize-readme.ts
│   │   ├── populate-content.ts
│   │   ├── readme-best-practices.ts
│   │   ├── recommend-ssg.ts
│   │   ├── setup-playwright-tests.ts
│   │   ├── setup-structure.ts
│   │   ├── simulate-execution.ts
│   │   ├── sync-code-to-docs.ts
│   │   ├── test-local-deployment.ts
│   │   ├── track-documentation-freshness.ts
│   │   ├── update-existing-documentation.ts
│   │   ├── validate-content.ts
│   │   ├── validate-documentation-freshness.ts
│   │   ├── validate-readme-checklist.ts
│   │   └── verify-deployment.ts
│   ├── types
│   │   └── api.ts
│   ├── utils
│   │   ├── artifact-detector.ts
│   │   ├── ast-analyzer.ts
│   │   ├── change-watcher.ts
│   │   ├── code-scanner.ts
│   │   ├── content-extractor.ts
│   │   ├── drift-detector.ts
│   │   ├── execution-simulator.ts
│   │   ├── freshness-tracker.ts
│   │   ├── language-parsers-simple.ts
│   │   ├── llm-client.ts
│   │   ├── permission-checker.ts
│   │   ├── semantic-analyzer.ts
│   │   ├── sitemap-generator.ts
│   │   ├── usage-metadata.ts
│   │   └── user-feedback-integration.ts
│   └── workflows
│       └── documentation-workflow.ts
├── test-docs-local.sh
├── tests
│   ├── api
│   │   └── mcp-responses.test.ts
│   ├── benchmarks
│   │   └── performance.test.ts
│   ├── call-graph-builder.test.ts
│   ├── change-watcher-priority.integration.test.ts
│   ├── change-watcher.test.ts
│   ├── edge-cases
│   │   └── error-handling.test.ts
│   ├── execution-simulator.test.ts
│   ├── functional
│   │   └── tools.test.ts
│   ├── integration
│   │   ├── kg-documentation-workflow.test.ts
│   │   ├── knowledge-graph-workflow.test.ts
│   │   ├── mcp-readme-tools.test.ts
│   │   ├── memory-mcp-tools.test.ts
│   │   ├── readme-technical-writer.test.ts
│   │   └── workflow.test.ts
│   ├── memory
│   │   ├── contextual-retrieval.test.ts
│   │   ├── enhanced-manager.test.ts
│   │   ├── export-import.test.ts
│   │   ├── freshness-kg-integration.test.ts
│   │   ├── kg-code-integration.test.ts
│   │   ├── kg-health.test.ts
│   │   ├── kg-link-validator.test.ts
│   │   ├── kg-storage-validation.test.ts
│   │   ├── kg-storage.test.ts
│   │   ├── knowledge-graph-documentation-examples.test.ts
│   │   ├── knowledge-graph-enhanced.test.ts
│   │   ├── knowledge-graph.test.ts
│   │   ├── learning.test.ts
│   │   ├── manager-advanced.test.ts
│   │   ├── manager.test.ts
│   │   ├── mcp-resource-integration.test.ts
│   │   ├── mcp-tool-persistence.test.ts
│   │   ├── schemas-documentation-examples.test.ts
│   │   ├── schemas.test.ts
│   │   ├── storage.test.ts
│   │   ├── temporal-analysis.test.ts
│   │   └── user-preferences.test.ts
│   ├── performance
│   │   ├── memory-load-testing.test.ts
│   │   └── memory-stress-testing.test.ts
│   ├── prompts
│   │   ├── guided-workflow-prompts.test.ts
│   │   └── technical-writer-prompts.test.ts
│   ├── server.test.ts
│   ├── setup.ts
│   ├── tools
│   │   ├── all-tools.test.ts
│   │   ├── analyze-coverage.test.ts
│   │   ├── analyze-deployments.test.ts
│   │   ├── analyze-readme.test.ts
│   │   ├── analyze-repository.test.ts
│   │   ├── check-documentation-links.test.ts
│   │   ├── cleanup-agent-artifacts.test.ts
│   │   ├── deploy-pages-kg-retrieval.test.ts
│   │   ├── deploy-pages-tracking.test.ts
│   │   ├── deploy-pages.test.ts
│   │   ├── detect-gaps.test.ts
│   │   ├── evaluate-readme-health.test.ts
│   │   ├── generate-contextual-content.test.ts
│   │   ├── generate-llm-context.test.ts
│   │   ├── generate-readme-template.test.ts
│   │   ├── generate-technical-writer-prompts.test.ts
│   │   ├── kg-health-check.test.ts
│   │   ├── manage-sitemap.test.ts
│   │   ├── optimize-readme.test.ts
│   │   ├── readme-best-practices.test.ts
│   │   ├── recommend-ssg-historical.test.ts
│   │   ├── recommend-ssg-preferences.test.ts
│   │   ├── recommend-ssg.test.ts
│   │   ├── simple-coverage.test.ts
│   │   ├── sync-code-to-docs.test.ts
│   │   ├── test-local-deployment.test.ts
│   │   ├── tool-error-handling.test.ts
│   │   ├── track-documentation-freshness.test.ts
│   │   ├── validate-content.test.ts
│   │   ├── validate-documentation-freshness.test.ts
│   │   └── validate-readme-checklist.test.ts
│   ├── types
│   │   └── type-safety.test.ts
│   └── utils
│       ├── artifact-detector.test.ts
│       ├── ast-analyzer.test.ts
│       ├── content-extractor.test.ts
│       ├── drift-detector-diataxis.test.ts
│       ├── drift-detector-priority.test.ts
│       ├── drift-detector.test.ts
│       ├── freshness-tracker.test.ts
│       ├── llm-client.test.ts
│       ├── semantic-analyzer.test.ts
│       ├── sitemap-generator.test.ts
│       ├── usage-metadata.test.ts
│       └── user-feedback-integration.test.ts
├── tsconfig.json
└── typedoc.json
```

# Files

--------------------------------------------------------------------------------
/src/memory/export-import.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Memory Export/Import System for DocuMCP
 * Comprehensive data portability, backup, and migration capabilities
 */

import { EventEmitter } from "events";
import { promises as fs } from "fs";
import { createWriteStream } from "fs";
import { MemoryEntry, JSONLStorage } from "./storage.js";
import { MemoryManager } from "./manager.js";
import { IncrementalLearningSystem } from "./learning.js";
import { KnowledgeGraph } from "./knowledge-graph.js";
import { MemoryPruningSystem } from "./pruning.js";

export interface ExportOptions {
  format: "json" | "jsonl" | "csv" | "xml" | "yaml" | "sqlite" | "archive";
  compression?: "gzip" | "zip" | "none";
  includeMetadata: boolean;
  includeLearning: boolean;
  includeKnowledgeGraph: boolean;
  filters?: {
    types?: string[];
    dateRange?: { start: Date; end: Date };
    projects?: string[];
    tags?: string[];
    outcomes?: string[];
  };
  anonymize?: {
    enabled: boolean;
    fields: string[];
    method: "hash" | "remove" | "pseudonymize";
  };
  encryption?: {
    enabled: boolean;
    algorithm: "aes-256-gcm" | "aes-192-gcm" | "aes-128-gcm";
    password?: string;
  };
}

export interface ImportOptions {
  format: "json" | "jsonl" | "csv" | "xml" | "yaml" | "sqlite" | "archive";
  mode: "merge" | "replace" | "append" | "update";
  validation: "strict" | "loose" | "none";
  conflictResolution: "skip" | "overwrite" | "merge" | "rename";
  backup: boolean;
  dryRun: boolean;
  mapping?: Record<string, string>; // Field mapping for different schemas
  transformation?: {
    enabled: boolean;
    rules: Array<{
      field: string;
      operation: "convert" | "transform" | "validate";
      params: any;
    }>;
  };
}

export interface ExportResult {
  success: boolean;
  filePath?: string;
  format: string;
  size: number;
  entries: number;
  metadata: {
    exportedAt: Date;
    version: string;
    source: string;
    includes: string[];
    compression?: string;
    encryption?: boolean;
  };
  warnings: string[];
  errors: string[];
}

export interface ImportResult {
  success: boolean;
  processed: number;
  imported: number;
  skipped: number;
  errors: number;
  errorDetails: string[]; // Detailed error messages
  conflicts: number;
  validation: {
    valid: number;
    invalid: number;
    warnings: string[];
  };
  summary: {
    newEntries: number;
    updatedEntries: number;
    duplicateEntries: number;
    failedEntries: number;
  };
  metadata: {
    importedAt: Date;
    source: string;
    format: string;
    mode: string;
  };
}

export interface MigrationPlan {
  sourceSystem: string;
  targetSystem: string;
  mapping: Record<string, string>;
  transformations: Array<{
    field: string;
    type: "rename" | "convert" | "merge" | "split" | "calculate";
    source: string | string[];
    target: string;
    operation?: string;
  }>;
  validation: Array<{
    field: string;
    rules: string[];
    required: boolean;
  }>;
  postProcessing: string[];
}

export interface ArchiveMetadata {
  version: string;
  created: Date;
  source: string;
  description: string;
  manifest: {
    files: Array<{
      name: string;
      type: string;
      size: number;
      checksum: string;
      entries?: number;
    }>;
    total: {
      files: number;
      size: number;
      entries: number;
    };
  };
  options: ExportOptions;
}

export class MemoryExportImportSystem extends EventEmitter {
  private storage: JSONLStorage;
  private manager: MemoryManager;
  private learningSystem: IncrementalLearningSystem;
  private knowledgeGraph: KnowledgeGraph;
  private pruningSystem?: MemoryPruningSystem;
  private readonly version = "1.0.0";

  constructor(
    storage: JSONLStorage,
    manager: MemoryManager,
    learningSystem: IncrementalLearningSystem,
    knowledgeGraph: KnowledgeGraph,
    pruningSystem?: MemoryPruningSystem,
  ) {
    super();
    this.storage = storage;
    this.manager = manager;
    this.learningSystem = learningSystem;
    this.knowledgeGraph = knowledgeGraph;
    this.pruningSystem = pruningSystem;
  }

  /**
   * Export memory data to specified format
   */
  async exportMemories(
    outputPath: string,
    options: Partial<ExportOptions> = {},
  ): Promise<ExportResult> {
    const defaultOptions: ExportOptions = {
      format: "json",
      compression: "none",
      includeMetadata: true,
      includeLearning: true,
      includeKnowledgeGraph: true,
      anonymize: {
        enabled: false,
        fields: ["userId", "email", "personalInfo"],
        method: "hash",
      },
      encryption: {
        enabled: false,
        algorithm: "aes-256-gcm",
      },
    };

    const activeOptions = { ...defaultOptions, ...options };
    const startTime = Date.now();

    this.emit("export_started", { outputPath, options: activeOptions });

    try {
      // Get filtered entries
      const entries = await this.getFilteredEntries(activeOptions.filters);

      // Prepare export data
      const exportData = await this.prepareExportData(entries, activeOptions);

      // Apply anonymization if enabled
      if (activeOptions.anonymize?.enabled) {
        this.applyAnonymization(exportData, activeOptions.anonymize);
      }

      // Prepare output path - if compression is requested, use temp file first
      let actualOutputPath = outputPath;
      if (activeOptions.compression && activeOptions.compression !== "none") {
        // For compressed exports, export to temp file first
        if (outputPath.endsWith(".gz")) {
          actualOutputPath = outputPath.slice(0, -3); // Remove .gz suffix
        } else if (outputPath.endsWith(".zip")) {
          actualOutputPath = outputPath.slice(0, -4); // Remove .zip suffix
        }
      }

      // Export to specified format
      let filePath: string;
      let size = 0;

      switch (activeOptions.format) {
        case "json":
          filePath = await this.exportToJSON(
            actualOutputPath,
            exportData,
            activeOptions,
          );
          break;
        case "jsonl":
          filePath = await this.exportToJSONL(
            actualOutputPath,
            exportData,
            activeOptions,
          );
          break;
        case "csv":
          filePath = await this.exportToCSV(
            actualOutputPath,
            exportData,
            activeOptions,
          );
          break;
        case "xml":
          filePath = await this.exportToXML(
            actualOutputPath,
            exportData,
            activeOptions,
          );
          break;
        case "yaml":
          filePath = await this.exportToYAML(
            actualOutputPath,
            exportData,
            activeOptions,
          );
          break;
        case "sqlite":
          filePath = await this.exportToSQLite(
            actualOutputPath,
            exportData,
            activeOptions,
          );
          break;
        case "archive":
          filePath = await this.exportToArchive(
            actualOutputPath,
            exportData,
            activeOptions,
          );
          break;
        default:
          throw new Error(`Unsupported export format: ${activeOptions.format}`);
      }

      // Apply compression if specified
      if (activeOptions.compression && activeOptions.compression !== "none") {
        filePath = await this.applyCompression(
          filePath,
          activeOptions.compression,
          outputPath,
        );
      }

      // Apply encryption if enabled
      if (activeOptions.encryption?.enabled) {
        filePath = await this.applyEncryption(
          filePath,
          activeOptions.encryption,
        );
      }

      // Get file size
      const stats = await fs.stat(filePath);
      size = stats.size;

      const result: ExportResult = {
        success: true,
        filePath,
        format: activeOptions.format,
        size,
        entries: entries.length,
        metadata: {
          exportedAt: new Date(),
          version: this.version,
          source: "DocuMCP Memory System",
          includes: this.getIncludedComponents(activeOptions),
          compression:
            activeOptions.compression !== "none"
              ? activeOptions.compression
              : undefined,
          encryption: activeOptions.encryption?.enabled,
        },
        warnings: [],
        errors: [],
      };

      this.emit("export_completed", {
        result,
        duration: Date.now() - startTime,
      });

      return result;
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : String(error);
      this.emit("export_error", { error: errorMessage });

      return {
        success: false,
        format: activeOptions.format,
        size: 0,
        entries: 0,
        metadata: {
          exportedAt: new Date(),
          version: this.version,
          source: "DocuMCP Memory System",
          includes: [],
        },
        warnings: [],
        errors: [errorMessage],
      };
    }
  }

  /**
   * Import memory data from specified source
   */
  async importMemories(
    inputPath: string,
    options: Partial<ImportOptions> = {},
  ): Promise<ImportResult> {
    const defaultOptions: ImportOptions = {
      format: "json",
      mode: "merge",
      validation: "strict",
      conflictResolution: "skip",
      backup: true,
      dryRun: false,
    };

    const activeOptions = { ...defaultOptions, ...options };
    const startTime = Date.now();

    this.emit("import_started", { inputPath, options: activeOptions });

    try {
      // Create backup if requested
      if (activeOptions.backup && !activeOptions.dryRun) {
        await this.createBackup();
      }

      // Detect and verify format
      const detectedFormat = await this.detectFormat(inputPath);
      if (detectedFormat !== activeOptions.format) {
        this.emit("format_mismatch", {
          detected: detectedFormat,
          specified: activeOptions.format,
        });
      }

      // Load and parse import data
      const importData = await this.loadImportData(inputPath, activeOptions);

      // Validate import data
      const validationResult = await this.validateImportData(
        importData,
        activeOptions,
      );

      if (
        validationResult.invalid > 0 &&
        activeOptions.validation === "strict"
      ) {
        throw new Error(
          `Validation failed: ${validationResult.invalid} invalid entries`,
        );
      }

      // Process import data
      const result = await this.processImportData(importData, activeOptions);

      this.emit("import_completed", {
        result,
        duration: Date.now() - startTime,
      });

      return result;
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : String(error);
      this.emit("import_error", { error: errorMessage });

      return {
        success: false,
        processed: 0,
        imported: 0,
        skipped: 0,
        errors: 1,
        errorDetails: [errorMessage],
        conflicts: 0,
        validation: {
          valid: 0,
          invalid: 0,
          warnings: [],
        },
        summary: {
          newEntries: 0,
          updatedEntries: 0,
          duplicateEntries: 0,
          failedEntries: 0,
        },
        metadata: {
          importedAt: new Date(),
          source: inputPath,
          format: activeOptions.format,
          mode: activeOptions.mode,
        },
      };
    }
  }

  /**
   * Create migration plan between different systems
   */
  async createMigrationPlan(
    sourceSchema: any,
    targetSchema: any,
    options?: {
      autoMap?: boolean;
      preserveStructure?: boolean;
      customMappings?: Record<string, string>;
    },
  ): Promise<MigrationPlan> {
    const plan: MigrationPlan = {
      sourceSystem: sourceSchema.system || "Unknown",
      targetSystem: "DocuMCP",
      mapping: {},
      transformations: [],
      validation: [],
      postProcessing: [],
    };

    // Auto-generate field mappings
    if (options?.autoMap !== false) {
      plan.mapping = this.generateFieldMappings(sourceSchema, targetSchema);
    }

    // Apply custom mappings
    if (options?.customMappings) {
      Object.assign(plan.mapping, options.customMappings);
    }

    // Generate transformations
    plan.transformations = this.generateTransformations(
      sourceSchema,
      targetSchema,
      plan.mapping,
    );

    // Generate validation rules
    plan.validation = this.generateValidationRules(targetSchema);

    // Generate post-processing steps
    plan.postProcessing = this.generatePostProcessingSteps(targetSchema);

    return plan;
  }

  /**
   * Execute migration plan
   */
  async executeMigration(
    inputPath: string,
    migrationPlan: MigrationPlan,
    options?: Partial<ImportOptions>,
  ): Promise<ImportResult> {
    this.emit("migration_started", { inputPath, plan: migrationPlan });

    try {
      // Load source data
      const sourceData = await this.loadRawData(inputPath);

      // Apply transformations
      const transformedData = await this.applyTransformations(
        sourceData,
        migrationPlan,
      );

      // Convert to import format
      const importData = this.convertToImportFormat(
        transformedData,
        migrationPlan,
      );

      // Execute import with migration settings
      const importOptions: ImportOptions = {
        format: "json",
        mode: "merge",
        validation: "strict",
        conflictResolution: "merge",
        backup: true,
        dryRun: false,
        ...options,
        transformation: {
          enabled: true,
          rules: migrationPlan.transformations.map((t) => ({
            field: t.target,
            operation: t.type as any,
            params: { source: t.source, operation: t.operation },
          })),
        },
      };

      const result = await this.processImportData(importData, importOptions);

      // Execute post-processing
      if (migrationPlan.postProcessing.length > 0) {
        await this.executePostProcessing(migrationPlan.postProcessing);
      }

      this.emit("migration_completed", { result });
      return result;
    } catch (error) {
      this.emit("migration_error", {
        error: error instanceof Error ? error.message : String(error),
      });
      throw error;
    }
  }

  /**
   * Get supported formats
   */
  getSupportedFormats(): {
    export: string[];
    import: string[];
    compression: string[];
    encryption: string[];
  } {
    return {
      export: ["json", "jsonl", "csv", "xml", "yaml", "sqlite", "archive"],
      import: ["json", "jsonl", "csv", "xml", "yaml", "sqlite", "archive"],
      compression: ["gzip", "zip", "none"],
      encryption: ["aes-256-gcm", "aes-192-gcm", "aes-128-gcm"],
    };
  }

  /**
   * Validate export/import compatibility
   */
  async validateCompatibility(
    sourcePath: string,
    _targetSystem: string = "DocuMCP",
  ): Promise<{
    compatible: boolean;
    issues: string[];
    recommendations: string[];
    migrationRequired: boolean;
  }> {
    try {
      const format = await this.detectFormat(sourcePath);
      const sampleData = await this.loadSampleData(sourcePath, format);

      const issues: string[] = [];
      const recommendations: string[] = [];
      let compatible = true;
      let migrationRequired = false;

      // Check format compatibility
      if (!this.getSupportedFormats().import.includes(format)) {
        issues.push(`Unsupported format: ${format}`);
        compatible = false;
      }

      // Check schema compatibility
      const schemaIssues = this.validateSchema(sampleData);
      if (schemaIssues.length > 0) {
        issues.push(...schemaIssues);
        migrationRequired = true;
      }

      // Check data integrity
      const integrityIssues = this.validateDataIntegrity(sampleData);
      if (integrityIssues.length > 0) {
        issues.push(...integrityIssues);
        recommendations.push("Consider data cleaning before import");
      }

      // Generate recommendations
      if (migrationRequired) {
        recommendations.push("Create migration plan for schema transformation");
      }

      if (format === "csv") {
        recommendations.push(
          "Consider using JSON or JSONL for better data preservation",
        );
      }

      return {
        compatible,
        issues,
        recommendations,
        migrationRequired,
      };
    } catch (error) {
      return {
        compatible: false,
        issues: [error instanceof Error ? error.message : String(error)],
        recommendations: ["Verify file format and accessibility"],
        migrationRequired: false,
      };
    }
  }

  /**
   * Private helper methods
   */
  private async getFilteredEntries(
    filters?: ExportOptions["filters"],
  ): Promise<MemoryEntry[]> {
    let entries = await this.storage.getAll();

    if (!filters) return entries;

    // Apply type filter
    if (filters.types && filters.types.length > 0) {
      entries = entries.filter((entry) => filters.types!.includes(entry.type));
    }

    // Apply date range filter
    if (filters.dateRange) {
      entries = entries.filter((entry) => {
        const entryDate = new Date(entry.timestamp);
        return (
          entryDate >= filters.dateRange!.start &&
          entryDate <= filters.dateRange!.end
        );
      });
    }

    // Apply project filter
    if (filters.projects && filters.projects.length > 0) {
      entries = entries.filter((entry) =>
        filters.projects!.some(
          (project) =>
            entry.data.projectPath?.includes(project) ||
            entry.data.projectId === project,
        ),
      );
    }

    // Apply tags filter
    if (filters.tags && filters.tags.length > 0) {
      entries = entries.filter(
        (entry) => entry.tags?.some((tag) => filters.tags!.includes(tag)),
      );
    }

    // Apply outcomes filter
    if (filters.outcomes && filters.outcomes.length > 0) {
      entries = entries.filter(
        (entry) =>
          filters.outcomes!.includes(entry.data.outcome) ||
          (entry.data.success === true &&
            filters.outcomes!.includes("success")) ||
          (entry.data.success === false &&
            filters.outcomes!.includes("failure")),
      );
    }

    return entries;
  }

  private async prepareExportData(
    entries: MemoryEntry[],
    options: ExportOptions,
  ): Promise<any> {
    const exportData: any = {
      metadata: {
        version: this.version,
        exportedAt: new Date().toISOString(),
        source: "DocuMCP Memory System",
        entries: entries.length,
        options: {
          includeMetadata: options.includeMetadata,
          includeLearning: options.includeLearning,
          includeKnowledgeGraph: options.includeKnowledgeGraph,
        },
      },
      memories: entries,
    };

    // Include learning data if requested
    if (options.includeLearning) {
      const patterns = await this.learningSystem.getPatterns();
      exportData.learning = {
        patterns,
        statistics: await this.learningSystem.getStatistics(),
      };
    }

    // Include knowledge graph if requested
    if (options.includeKnowledgeGraph) {
      const nodes = await this.knowledgeGraph.getAllNodes();
      const edges = await this.knowledgeGraph.getAllEdges();
      exportData.knowledgeGraph = {
        nodes,
        edges,
        statistics: await this.knowledgeGraph.getStatistics(),
      };
    }

    return exportData;
  }

  private applyAnonymization(
    data: any,
    anonymizeOptions: { fields: string[]; method: string },
  ): void {
    const anonymizeValue = (value: any, method: string): any => {
      if (typeof value !== "string") return value;

      switch (method) {
        case "hash":
          return this.hashValue(value);
        case "remove":
          return null;
        case "pseudonymize":
          return this.pseudonymizeValue(value);
        default:
          return value;
      }
    };

    const anonymizeObject = (obj: any): void => {
      for (const [key, value] of Object.entries(obj)) {
        if (anonymizeOptions.fields.includes(key)) {
          obj[key] = anonymizeValue(value, anonymizeOptions.method);
        } else if (typeof value === "object" && value !== null) {
          anonymizeObject(value);
        }
      }
    };

    anonymizeObject(data);
  }

  private hashValue(value: string): string {
    // Simple hash - in production, use a proper cryptographic hash
    let hash = 0;
    for (let i = 0; i < value.length; i++) {
      const char = value.charCodeAt(i);
      hash = (hash << 5) - hash + char;
      hash = hash & hash;
    }
    return `hash_${Math.abs(hash).toString(36)}`;
  }

  private pseudonymizeValue(_value: string): string {
    // Simple pseudonymization - in production, use proper techniques
    const prefixes = ["user", "project", "system", "item"];
    const suffix = Math.random().toString(36).substr(2, 8);
    const prefix = prefixes[Math.floor(Math.random() * prefixes.length)];
    return `${prefix}_${suffix}`;
  }

  private async exportToJSON(
    outputPath: string,
    data: any,
    _options: ExportOptions,
  ): Promise<string> {
    const jsonData = JSON.stringify(data, null, 2);
    // Handle compression-aware file paths (e.g., file.json.gz)
    let filePath = outputPath;
    if (!outputPath.includes(".json")) {
      filePath = `${outputPath}.json`;
    }
    await fs.writeFile(filePath, jsonData, "utf8");
    return filePath;
  }

  private async exportToJSONL(
    outputPath: string,
    data: any,
    _options: ExportOptions,
  ): Promise<string> {
    const filePath = outputPath.endsWith(".jsonl")
      ? outputPath
      : `${outputPath}.jsonl`;

    return new Promise((resolve, reject) => {
      const writeStream = createWriteStream(filePath);

      writeStream.on("error", (error) => {
        reject(error);
      });

      writeStream.on("finish", () => {
        resolve(filePath);
      });

      // Write metadata as first line
      writeStream.write(JSON.stringify(data.metadata) + "\n");

      // Write each memory entry as a separate line
      for (const entry of data.memories) {
        writeStream.write(JSON.stringify(entry) + "\n");
      }

      // Write learning data if included
      if (data.learning) {
        writeStream.write(
          JSON.stringify({ type: "learning", data: data.learning }) + "\n",
        );
      }

      // Write knowledge graph if included
      if (data.knowledgeGraph) {
        writeStream.write(
          JSON.stringify({
            type: "knowledgeGraph",
            data: data.knowledgeGraph,
          }) + "\n",
        );
      }

      writeStream.end();
    });
  }

  private async exportToCSV(
    outputPath: string,
    data: any,
    _options: ExportOptions,
  ): Promise<string> {
    const filePath = outputPath.endsWith(".csv")
      ? outputPath
      : `${outputPath}.csv`;

    // Flatten memory entries for CSV format
    const flattenedEntries = data.memories.map((entry: MemoryEntry) => ({
      id: entry.id,
      timestamp: entry.timestamp,
      type: entry.type,
      projectPath: entry.data.projectPath || "",
      projectId: entry.data.projectId || "",
      language: entry.data.language || "",
      framework: entry.data.framework || "",
      outcome: entry.data.outcome || "",
      success: entry.data.success || false,
      tags: entry.tags?.join(";") || "",
      metadata: JSON.stringify(entry.metadata || {}),
    }));

    // Generate CSV headers
    const headers = Object.keys(flattenedEntries[0] || {});
    const csvLines = [headers.join(",")];

    // Generate CSV rows
    for (const entry of flattenedEntries) {
      const row = headers.map((header) => {
        const value = entry[header as keyof typeof entry];
        const stringValue =
          typeof value === "string" ? value : JSON.stringify(value);
        return `"${stringValue.replace(/"/g, '""')}"`;
      });
      csvLines.push(row.join(","));
    }

    await fs.writeFile(filePath, csvLines.join("\n"), "utf8");
    return filePath;
  }

  private async exportToXML(
    outputPath: string,
    data: any,
    _options: ExportOptions,
  ): Promise<string> {
    const filePath = outputPath.endsWith(".xml")
      ? outputPath
      : `${outputPath}.xml`;

    const xmlData = this.convertToXML(data);
    await fs.writeFile(filePath, xmlData, "utf8");
    return filePath;
  }

  private async exportToYAML(
    outputPath: string,
    data: any,
    _options: ExportOptions,
  ): Promise<string> {
    const filePath = outputPath.endsWith(".yaml")
      ? outputPath
      : `${outputPath}.yaml`;

    // Simple YAML conversion - in production, use a proper YAML library
    const yamlData = this.convertToYAML(data);
    await fs.writeFile(filePath, yamlData, "utf8");
    return filePath;
  }

  private async exportToSQLite(
    _outputPath: string,
    _data: any,
    _options: ExportOptions,
  ): Promise<string> {
    // This would require a SQLite library like better-sqlite3
    // For now, throw an error indicating additional dependencies needed
    throw new Error(
      "SQLite export requires additional dependencies (better-sqlite3)",
    );
  }

  private async exportToArchive(
    outputPath: string,
    data: any,
    options: ExportOptions,
  ): Promise<string> {
    const archivePath = outputPath.endsWith(".tar")
      ? outputPath
      : `${outputPath}.tar`;

    // Create archive metadata
    const metadata: ArchiveMetadata = {
      version: this.version,
      created: new Date(),
      source: "DocuMCP Memory System",
      description: "Complete memory system export archive",
      manifest: {
        files: [],
        total: { files: 0, size: 0, entries: data.memories.length },
      },
      options,
    };

    // This would require archiving capabilities
    // For now, create multiple files and reference them in metadata
    const baseDir = archivePath.replace(".tar", "");
    await fs.mkdir(baseDir, { recursive: true });

    // Export memories as JSON
    const memoriesPath = `${baseDir}/memories.json`;
    await this.exportToJSON(memoriesPath, { memories: data.memories }, options);
    metadata.manifest.files.push({
      name: "memories.json",
      type: "memories",
      size: (await fs.stat(memoriesPath)).size,
      checksum: "sha256-placeholder",
      entries: data.memories.length,
    });

    // Export learning data if included
    if (data.learning) {
      const learningPath = `${baseDir}/learning.json`;
      await this.exportToJSON(learningPath, data.learning, options);
      metadata.manifest.files.push({
        name: "learning.json",
        type: "learning",
        size: (await fs.stat(learningPath)).size,
        checksum: "sha256-placeholder",
      });
    }

    // Export knowledge graph if included
    if (data.knowledgeGraph) {
      const kgPath = `${baseDir}/knowledge-graph.json`;
      await this.exportToJSON(kgPath, data.knowledgeGraph, options);
      metadata.manifest.files.push({
        name: "knowledge-graph.json",
        type: "knowledge-graph",
        size: (await fs.stat(kgPath)).size,
        checksum: "sha256-placeholder",
      });
    }

    // Write metadata
    const metadataPath = `${baseDir}/metadata.json`;
    await this.exportToJSON(metadataPath, metadata, options);

    return baseDir;
  }

  private async applyCompression(
    filePath: string,
    compression: string,
    targetPath?: string,
  ): Promise<string> {
    if (compression === "gzip") {
      const compressedPath = targetPath || `${filePath}.gz`;
      const content = await fs.readFile(filePath, "utf8");
      // Simple mock compression - just add a header and write the content
      await fs.writeFile(compressedPath, `GZIP_HEADER\n${content}`, "utf8");

      // Clean up temp file if we used one
      if (targetPath && targetPath !== filePath) {
        await fs.unlink(filePath);
      }

      return compressedPath;
    }

    // For other compression types or 'none', return original path
    this.emit("compression_skipped", {
      reason: "Not implemented",
      compression,
    });
    return filePath;
  }

  private async applyEncryption(
    filePath: string,
    encryption: any,
  ): Promise<string> {
    // This would require encryption capabilities
    // For now, return the original path
    this.emit("encryption_skipped", { reason: "Not implemented", encryption });
    return filePath;
  }

  private getIncludedComponents(options: ExportOptions): string[] {
    const components = ["memories"];
    if (options.includeMetadata) components.push("metadata");
    if (options.includeLearning) components.push("learning");
    if (options.includeKnowledgeGraph) components.push("knowledge-graph");
    return components;
  }

  private async detectFormat(filePath: string): Promise<string> {
    const extension = filePath.split(".").pop()?.toLowerCase();

    switch (extension) {
      case "json":
        return "json";
      case "jsonl":
        return "jsonl";
      case "csv":
        return "csv";
      case "xml":
        return "xml";
      case "yaml":
      case "yml":
        return "yaml";
      case "db":
      case "sqlite":
        return "sqlite";
      case "tar":
      case "zip":
        return "archive";
      default: {
        // Try to detect by content
        const content = await fs.readFile(filePath, "utf8");
        if (content.trim().startsWith("{") || content.trim().startsWith("[")) {
          return "json";
        }
        if (content.includes("<?xml")) {
          return "xml";
        }
        return "unknown";
      }
    }
  }

  private async loadImportData(
    filePath: string,
    options: ImportOptions,
  ): Promise<any> {
    switch (options.format) {
      case "json":
        return JSON.parse(await fs.readFile(filePath, "utf8"));
      case "jsonl":
        return this.loadJSONLData(filePath);
      case "csv":
        return this.loadCSVData(filePath);
      case "xml":
        return this.loadXMLData(filePath);
      case "yaml":
        return this.loadYAMLData(filePath);
      default:
        throw new Error(`Unsupported import format: ${options.format}`);
    }
  }

  private async loadJSONLData(filePath: string): Promise<any> {
    const content = await fs.readFile(filePath, "utf8");
    const lines = content.trim().split("\n");

    const data: any = { memories: [], learning: null, knowledgeGraph: null };

    for (const line of lines) {
      const parsed = JSON.parse(line);

      if (parsed.type === "learning") {
        data.learning = parsed.data;
      } else if (parsed.type === "knowledgeGraph") {
        data.knowledgeGraph = parsed.data;
      } else if (parsed.version) {
        data.metadata = parsed;
      } else {
        data.memories.push(parsed);
      }
    }

    return data;
  }

  private async loadCSVData(filePath: string): Promise<any> {
    const content = await fs.readFile(filePath, "utf8");
    const lines = content.trim().split("\n");
    const headers = lines[0].split(",").map((h) => h.replace(/"/g, ""));

    const memories = [];
    for (let i = 1; i < lines.length; i++) {
      const values = this.parseCSVLine(lines[i]);
      const entry: any = {};

      for (let j = 0; j < headers.length; j++) {
        const header = headers[j];
        const value = values[j];

        // Parse special fields
        if (header === "tags") {
          entry.tags = value ? value.split(";") : [];
        } else if (header === "metadata") {
          try {
            entry.metadata = JSON.parse(value);
          } catch {
            entry.metadata = {};
          }
        } else if (header === "success") {
          entry.data = entry.data || {};
          entry.data.success = value === "true";
        } else if (
          [
            "projectPath",
            "projectId",
            "language",
            "framework",
            "outcome",
          ].includes(header)
        ) {
          entry.data = entry.data || {};
          entry.data[header] = value;
        } else {
          entry[header] = value;
        }
      }

      memories.push(entry);
    }

    return { memories };
  }

  private parseCSVLine(line: string): string[] {
    const values: string[] = [];
    let current = "";
    let inQuotes = false;

    for (let i = 0; i < line.length; i++) {
      const char = line[i];

      if (char === '"') {
        if (inQuotes && line[i + 1] === '"') {
          current += '"';
          i++;
        } else {
          inQuotes = !inQuotes;
        }
      } else if (char === "," && !inQuotes) {
        values.push(current);
        current = "";
      } else {
        current += char;
      }
    }

    values.push(current);
    return values;
  }

  private async loadXMLData(_filePath: string): Promise<any> {
    // This would require an XML parser
    throw new Error("XML import requires additional dependencies (xml2js)");
  }

  private async loadYAMLData(_filePath: string): Promise<any> {
    // This would require a YAML parser
    throw new Error("YAML import requires additional dependencies (js-yaml)");
  }

  private async validateImportData(
    data: any,
    options: ImportOptions,
  ): Promise<{ valid: number; invalid: number; warnings: string[] }> {
    const result = { valid: 0, invalid: 0, warnings: [] as string[] };

    if (!data.memories || !Array.isArray(data.memories)) {
      result.warnings.push("No memories array found in import data");
      return result;
    }

    for (const entry of data.memories) {
      if (this.validateMemoryEntry(entry, options.validation)) {
        result.valid++;
      } else {
        result.invalid++;
      }
    }

    return result;
  }

  private validateMemoryEntry(entry: any, validation: string): boolean {
    // Check for completely missing or null required fields
    if (
      !entry.id ||
      !entry.timestamp ||
      entry.type === null ||
      entry.type === undefined ||
      entry.data === null
    ) {
      return false; // These are invalid regardless of validation level
    }

    if (!entry.type) {
      return validation !== "strict";
    }

    if (validation === "strict") {
      return Boolean(entry.data && typeof entry.data === "object");
    }

    // For loose validation, still require data to be defined (not null)
    if (validation === "loose" && entry.data === null) {
      return false;
    }

    return true;
  }

  private async processImportData(
    data: any,
    options: ImportOptions,
  ): Promise<ImportResult> {
    const result: ImportResult = {
      success: true,
      processed: 0,
      imported: 0,
      skipped: 0,
      errors: 0,
      errorDetails: [],
      conflicts: 0,
      validation: { valid: 0, invalid: 0, warnings: [] },
      summary: {
        newEntries: 0,
        updatedEntries: 0,
        duplicateEntries: 0,
        failedEntries: 0,
      },
      metadata: {
        importedAt: new Date(),
        source: "imported data",
        format: options.format,
        mode: options.mode,
      },
    };

    if (!data.memories || !Array.isArray(data.memories)) {
      result.success = false;
      result.errors = 1;
      result.errorDetails = ["No valid memories array found in import data"];
      return result;
    }

    for (const entry of data.memories) {
      result.processed++;

      try {
        // Apply transformations and mappings
        let transformedEntry = { ...entry };
        if (options.mapping || options.transformation?.enabled) {
          transformedEntry = this.applyDataTransformations(entry, options);
        }

        if (!this.validateMemoryEntry(transformedEntry, options.validation)) {
          result.validation.invalid++;
          result.errors++;
          result.summary.failedEntries++;
          result.errorDetails.push(
            `Invalid memory entry: ${
              transformedEntry.id || "unknown"
            } - validation failed`,
          );
          continue;
        }

        result.validation.valid++;

        // Check for conflicts
        const existing = await this.storage.get(transformedEntry.id);
        if (existing) {
          result.conflicts++;

          switch (options.conflictResolution) {
            case "skip":
              result.skipped++;
              result.summary.duplicateEntries++;
              continue;
            case "overwrite":
              if (!options.dryRun) {
                await this.storage.update(
                  transformedEntry.id,
                  transformedEntry,
                );
                result.imported++;
                result.summary.updatedEntries++;
              }
              break;
            case "merge":
              if (!options.dryRun) {
                const merged = this.mergeEntries(existing, transformedEntry);
                await this.storage.update(transformedEntry.id, merged);
                result.imported++;
                result.summary.updatedEntries++;
              }
              break;
            case "rename": {
              const newId = `${transformedEntry.id}_imported_${Date.now()}`;
              if (!options.dryRun) {
                await this.storage.store({ ...transformedEntry, id: newId });
                result.imported++;
                result.summary.newEntries++;
              }
              break;
            }
          }
        } else {
          if (!options.dryRun) {
            await this.storage.store(transformedEntry);
            result.imported++;
            result.summary.newEntries++;
          }
        }
      } catch (error) {
        result.errors++;
        result.summary.failedEntries++;
        result.errorDetails.push(
          error instanceof Error ? error.message : String(error),
        );
      }
    }

    // Import learning data if present
    if (data.learning && !options.dryRun) {
      await this.importLearningData(data.learning);
    }

    // Import knowledge graph if present
    if (data.knowledgeGraph && !options.dryRun) {
      await this.importKnowledgeGraphData(data.knowledgeGraph);
    }

    return result;
  }

  private mergeEntries(
    existing: MemoryEntry,
    imported: MemoryEntry,
  ): MemoryEntry {
    return {
      ...existing,
      ...imported,
      data: { ...existing.data, ...imported.data },
      metadata: { ...existing.metadata, ...imported.metadata },
      tags: [...new Set([...(existing.tags || []), ...(imported.tags || [])])],
      timestamp: imported.timestamp || existing.timestamp,
    };
  }

  private async importLearningData(learningData: any): Promise<void> {
    if (learningData.patterns && Array.isArray(learningData.patterns)) {
      for (const pattern of learningData.patterns) {
        // This would require methods to import patterns into the learning system
        // For now, just emit an event
        this.emit("learning_pattern_imported", pattern);
      }
    }
  }

  private async importKnowledgeGraphData(kgData: any): Promise<void> {
    if (kgData.nodes && Array.isArray(kgData.nodes)) {
      for (const node of kgData.nodes) {
        await this.knowledgeGraph.addNode(node);
      }
    }

    if (kgData.edges && Array.isArray(kgData.edges)) {
      for (const edge of kgData.edges) {
        await this.knowledgeGraph.addEdge(edge);
      }
    }
  }

  private async createBackup(): Promise<string> {
    const backupPath = `backup_${Date.now()}.json`;
    const exportResult = await this.exportMemories(backupPath, {
      format: "json",
      includeMetadata: true,
      includeLearning: true,
      includeKnowledgeGraph: true,
    });

    this.emit("backup_created", { path: exportResult.filePath });
    return exportResult.filePath || backupPath;
  }

  private convertToXML(data: any): string {
    // Simple XML conversion - in production, use a proper XML library
    const escapeXML = (str: string) =>
      str
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#x27;");

    let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<export>\n';
    xml += `  <metadata>\n`;
    xml += `    <version>${escapeXML(data.metadata.version)}</version>\n`;
    xml += `    <exportedAt>${escapeXML(
      data.metadata.exportedAt,
    )}</exportedAt>\n`;
    xml += `    <entries>${data.metadata.entries}</entries>\n`;
    xml += `  </metadata>\n`;
    xml += `  <memories>\n`;

    for (const memory of data.memories) {
      xml += `    <memory>\n`;
      xml += `      <id>${escapeXML(memory.id)}</id>\n`;
      xml += `      <timestamp>${escapeXML(memory.timestamp)}</timestamp>\n`;
      xml += `      <type>${escapeXML(memory.type)}</type>\n`;
      xml += `      <data>${escapeXML(JSON.stringify(memory.data))}</data>\n`;
      xml += `    </memory>\n`;
    }

    xml += `  </memories>\n`;
    xml += "</export>";

    return xml;
  }

  private convertToYAML(data: any): string {
    // Simple YAML conversion - in production, use a proper YAML library
    const indent = (level: number) => "  ".repeat(level);
    const toYAML = (obj: any, level: number = 0): string => {
      if (obj === null) return "null";
      if (typeof obj === "boolean") return obj.toString();
      if (typeof obj === "number") return obj.toString();
      if (typeof obj === "string") return `"${obj.replace(/"/g, '\\"')}"`;

      if (Array.isArray(obj)) {
        if (obj.length === 0) return "[]";
        return (
          "\n" +
          obj
            .map(
              (item) => `${indent(level)}- ${toYAML(item, level + 1).trim()}`,
            )
            .join("\n")
        );
      }

      if (typeof obj === "object") {
        const keys = Object.keys(obj);
        if (keys.length === 0) return "{}";
        return (
          "\n" +
          keys
            .map(
              (key) =>
                `${indent(level)}${key}: ${toYAML(obj[key], level + 1).trim()}`,
            )
            .join("\n")
        );
      }

      return obj.toString();
    };

    return `# DocuMCP Memory Export\n${toYAML(data)}`;
  }

  // Additional helper methods for migration
  private generateFieldMappings(
    sourceSchema: any,
    targetSchema: any,
  ): Record<string, string> {
    const mappings: Record<string, string> = {};

    // Simple field name matching - in production, use more sophisticated mapping
    const sourceFields = Object.keys(sourceSchema.fields || {});
    const targetFields = Object.keys(targetSchema.fields || {});

    for (const sourceField of sourceFields) {
      // Direct match
      if (targetFields.includes(sourceField)) {
        mappings[sourceField] = sourceField;
        continue;
      }

      // Fuzzy matching
      const similar = targetFields.find(
        (tf) =>
          tf.toLowerCase().includes(sourceField.toLowerCase()) ||
          sourceField.toLowerCase().includes(tf.toLowerCase()),
      );

      if (similar) {
        mappings[sourceField] = similar;
      }
    }

    return mappings;
  }

  private generateTransformations(
    sourceSchema: any,
    targetSchema: any,
    mapping: Record<string, string>,
  ): MigrationPlan["transformations"] {
    const transformations: MigrationPlan["transformations"] = [];

    // Generate transformations based on field mappings and type differences
    for (const [sourceField, targetField] of Object.entries(mapping)) {
      const sourceType = sourceSchema.fields?.[sourceField]?.type;
      const targetType = targetSchema.fields?.[targetField]?.type;

      if (sourceType !== targetType) {
        transformations.push({
          field: targetField,
          type: "convert",
          source: sourceField,
          target: targetField,
          operation: `${sourceType}_to_${targetType}`,
        });
      } else {
        transformations.push({
          field: targetField,
          type: "rename",
          source: sourceField,
          target: targetField,
        });
      }
    }

    return transformations;
  }

  private generateValidationRules(
    targetSchema: any,
  ): MigrationPlan["validation"] {
    const validation: MigrationPlan["validation"] = [];

    // Generate validation rules based on target schema
    if (targetSchema.fields) {
      for (const [field, config] of Object.entries(targetSchema.fields)) {
        const rules: string[] = [];
        const fieldConfig = config as any;

        if (fieldConfig.required) {
          rules.push("required");
        }

        if (fieldConfig.type) {
          rules.push(`type:${fieldConfig.type}`);
        }

        if (fieldConfig.format) {
          rules.push(`format:${fieldConfig.format}`);
        }

        validation.push({
          field,
          rules,
          required: fieldConfig.required || false,
        });
      }
    }

    return validation;
  }

  private generatePostProcessingSteps(targetSchema: any): string[] {
    const steps: string[] = [];

    // Generate post-processing steps
    steps.push("rebuild_indices");
    steps.push("update_references");
    steps.push("validate_integrity");

    if (targetSchema.features?.learning) {
      steps.push("retrain_models");
    }

    if (targetSchema.features?.knowledgeGraph) {
      steps.push("rebuild_graph");
    }

    return steps;
  }

  private async loadRawData(inputPath: string): Promise<any> {
    const content = await fs.readFile(inputPath, "utf8");
    try {
      return JSON.parse(content);
    } catch {
      return { raw: content };
    }
  }

  private async applyTransformations(
    data: any,
    plan: MigrationPlan,
  ): Promise<any> {
    const transformed = JSON.parse(JSON.stringify(data)); // Deep clone

    for (const transformation of plan.transformations) {
      // Apply transformation based on type
      switch (transformation.type) {
        case "rename":
          this.renameField(
            transformed,
            transformation.source as string,
            transformation.target,
          );
          break;
        case "convert":
          this.convertField(
            transformed,
            transformation.source as string,
            transformation.target,
            transformation.operation,
          );
          break;
        // Add more transformation types as needed
      }
    }

    return transformed;
  }

  private renameField(obj: any, oldName: string, newName: string): void {
    if (typeof obj !== "object" || obj === null) return;

    if (Array.isArray(obj)) {
      obj.forEach((item) => this.renameField(item, oldName, newName));
    } else {
      if (oldName in obj) {
        obj[newName] = obj[oldName];
        delete obj[oldName];
      }

      Object.values(obj).forEach((value) =>
        this.renameField(value, oldName, newName),
      );
    }
  }

  private convertField(
    obj: any,
    fieldName: string,
    targetName: string,
    operation?: string,
  ): void {
    if (typeof obj !== "object" || obj === null) return;

    if (Array.isArray(obj)) {
      obj.forEach((item) =>
        this.convertField(item, fieldName, targetName, operation),
      );
    } else {
      if (fieldName in obj) {
        const value = obj[fieldName];

        // Apply conversion based on operation
        switch (operation) {
          case "string_to_number":
            obj[targetName] = Number(value);
            break;
          case "number_to_string":
            obj[targetName] = String(value);
            break;
          case "array_to_string":
            obj[targetName] = Array.isArray(value) ? value.join(",") : value;
            break;
          case "string_to_array":
            obj[targetName] =
              typeof value === "string" ? value.split(",") : value;
            break;
          default:
            obj[targetName] = value;
        }

        if (fieldName !== targetName) {
          delete obj[fieldName];
        }
      }

      Object.values(obj).forEach((value) =>
        this.convertField(value, fieldName, targetName, operation),
      );
    }
  }

  private convertToImportFormat(data: any, plan: MigrationPlan): any {
    // Convert transformed data to standard import format
    const memories = Array.isArray(data) ? data : data.memories || [data];

    // Convert old format to new MemoryEntry format
    const convertedMemories = memories.map((entry: any) => {
      // If already in new format, return as-is
      if (entry.data && entry.metadata) {
        return entry;
      }

      // Convert old flat format to new structured format
      const converted: any = {
        id:
          entry.id ||
          `migrated_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        type: entry.type || "analysis",
        timestamp: entry.timestamp || new Date().toISOString(),
        data: {},
        metadata: {},
      };

      // Move known fields to appropriate locations
      const dataFields = [
        "language",
        "recommendation",
        "framework",
        "outcome",
        "success",
      ];
      const metadataFields = [
        "project",
        "projectId",
        "repository",
        "ssg",
        "tags",
      ];

      for (const [key, value] of Object.entries(entry)) {
        if (["id", "type", "timestamp"].includes(key)) {
          // Already handled above
          continue;
        } else if (dataFields.includes(key)) {
          converted.data[key] = value;
        } else if (metadataFields.includes(key)) {
          if (key === "project") {
            converted.metadata.projectId = value; // Convert old 'project' field to 'projectId'
          } else {
            converted.metadata[key] = value;
          }
        } else {
          // Put unknown fields in data
          converted.data[key] = value;
        }
      }

      return converted;
    });

    return {
      metadata: {
        version: this.version,
        migrated: true,
        migrationPlan: plan.sourceSystem,
        importedAt: new Date().toISOString(),
      },
      memories: convertedMemories,
    };
  }

  private async executePostProcessing(steps: string[]): Promise<void> {
    for (const step of steps) {
      try {
        switch (step) {
          case "rebuild_indices":
            await this.storage.rebuildIndex();
            break;
          case "update_references":
            // Update cross-references in data
            break;
          case "validate_integrity":
            // Validate data integrity
            break;
          case "retrain_models":
            // Trigger learning system retraining
            break;
          case "rebuild_graph":
            // Rebuild knowledge graph
            break;
        }

        this.emit("post_processing_step_completed", { step });
      } catch (error) {
        this.emit("post_processing_step_failed", {
          step,
          error: error instanceof Error ? error.message : String(error),
        });
      }
    }
  }

  private async loadSampleData(
    sourcePath: string,
    format: string,
  ): Promise<any> {
    // Load a small sample of data for validation
    if (format === "json") {
      const content = await fs.readFile(sourcePath, "utf8");
      const data = JSON.parse(content);

      if (data.memories && Array.isArray(data.memories)) {
        return { memories: data.memories.slice(0, 10) }; // First 10 entries
      }

      return data;
    }

    // For other formats, return basic structure info
    return { format, sampleLoaded: true };
  }

  private validateSchema(sampleData: any): string[] {
    const issues: string[] = [];

    if (!sampleData.memories && !Array.isArray(sampleData)) {
      issues.push("Expected memories array not found");
    }

    const memories =
      sampleData.memories || (Array.isArray(sampleData) ? sampleData : []);

    if (memories.length > 0) {
      const firstEntry = memories[0];

      if (!firstEntry.id) {
        issues.push("Memory entries missing required id field");
      }

      if (!firstEntry.timestamp) {
        issues.push("Memory entries missing required timestamp field");
      }

      if (!firstEntry.type) {
        issues.push("Memory entries missing required type field");
      }

      if (!firstEntry.data) {
        issues.push("Memory entries missing required data field");
      }
    }

    return issues;
  }

  private validateDataIntegrity(sampleData: any): string[] {
    const issues: string[] = [];

    const memories =
      sampleData.memories || (Array.isArray(sampleData) ? sampleData : []);

    // Check for duplicate IDs
    const ids = new Set();
    const duplicates = new Set();

    for (const entry of memories) {
      if (entry.id) {
        if (ids.has(entry.id)) {
          duplicates.add(entry.id);
        } else {
          ids.add(entry.id);
        }
      }
    }

    if (duplicates.size > 0) {
      issues.push(`Found ${duplicates.size} duplicate IDs`);
    }

    // Check timestamp validity
    let invalidTimestamps = 0;
    for (const entry of memories) {
      if (entry.timestamp && isNaN(new Date(entry.timestamp).getTime())) {
        invalidTimestamps++;
      }
    }

    if (invalidTimestamps > 0) {
      issues.push(`Found ${invalidTimestamps} invalid timestamps`);
    }

    return issues;
  }

  /**
   * Apply field mappings and transformations to import data
   */
  private applyDataTransformations(entry: any, options: ImportOptions): any {
    const transformed = JSON.parse(JSON.stringify(entry)); // Deep clone

    // Apply field mappings first
    if (options.mapping) {
      for (const [sourcePath, targetPath] of Object.entries(options.mapping)) {
        const sourceValue = this.getValueByPath(transformed, sourcePath);
        if (sourceValue !== undefined) {
          this.setValueByPath(transformed, targetPath, sourceValue);
          this.deleteValueByPath(transformed, sourcePath);
        }
      }
    }

    // Apply transformations
    if (options.transformation?.enabled && options.transformation.rules) {
      for (const rule of options.transformation.rules) {
        switch (rule.operation) {
          case "transform":
            if (rule.params?.value !== undefined) {
              this.setValueByPath(transformed, rule.field, rule.params.value);
            }
            break;
          case "convert":
            // Apply conversion based on params
            break;
        }
      }
    }

    return transformed;
  }

  /**
   * Get value from object using dot notation path
   */
  private getValueByPath(obj: any, path: string): any {
    return path.split(".").reduce((current, key) => current?.[key], obj);
  }

  /**
   * Set value in object using dot notation path
   */
  private setValueByPath(obj: any, path: string, value: any): void {
    const keys = path.split(".");
    const lastKey = keys.pop()!;
    const target = keys.reduce((current, key) => {
      if (!(key in current)) {
        current[key] = {};
      }
      return current[key];
    }, obj);
    target[lastKey] = value;
  }

  /**
   * Delete value from object using dot notation path
   */
  private deleteValueByPath(obj: any, path: string): void {
    const keys = path.split(".");
    const lastKey = keys.pop()!;
    const target = keys.reduce((current, key) => current?.[key], obj);
    if (target && typeof target === "object") {
      delete target[lastKey];
    }
  }
}

```

--------------------------------------------------------------------------------
/src/tools/validate-content.ts:
--------------------------------------------------------------------------------

```typescript
import { Tool } from "@modelcontextprotocol/sdk/types.js";
import * as fs from "fs/promises";
import * as path from "path";
import { exec } from "child_process";
import { promisify } from "util";
import { handleMemoryRecall } from "../memory/index.js";
import {
  createExecutionSimulator,
  ExecutionSimulator,
} from "../utils/execution-simulator.js";
// ESM-compatible dirname replacement - fallback for test environments
function getDirname(): string {
  // Use process.cwd() as fallback for all environments to avoid import.meta issues
  return process.cwd();
}

const currentDir = getDirname();

const execAsync = promisify(exec);

interface ValidationOptions {
  contentPath: string;
  analysisId?: string;
  validationType: "accuracy" | "completeness" | "compliance" | "all";
  includeCodeValidation: boolean;
  confidence: "strict" | "moderate" | "permissive";
}

interface ConfidenceMetrics {
  overall: number;
  breakdown: {
    technologyDetection: number;
    frameworkVersionAccuracy: number;
    codeExampleRelevance: number;
    architecturalAssumptions: number;
    businessContextAlignment: number;
  };
  riskFactors: RiskFactor[];
}

interface RiskFactor {
  type: "high" | "medium" | "low";
  category: string;
  description: string;
  impact: string;
  mitigation: string;
}

interface UncertaintyFlag {
  area: string;
  severity: "low" | "medium" | "high" | "critical";
  description: string;
  potentialImpact: string;
  clarificationNeeded: string;
  fallbackStrategy: string;
}

interface ValidationIssue {
  type: "error" | "warning" | "info";
  category: "accuracy" | "completeness" | "compliance" | "performance";
  location: {
    file: string;
    line?: number;
    section?: string;
  };
  description: string;
  evidence: string[];
  suggestedFix: string;
  confidence: number;
}

interface CodeValidationResult {
  overallSuccess: boolean;
  exampleResults: ExampleValidation[];
  confidence: number;
}

interface ExampleValidation {
  example: string;
  compilationSuccess: boolean;
  executionSuccess: boolean;
  issues: ValidationIssue[];
  confidence: number;
}

export interface ValidationResult {
  success: boolean;
  confidence: ConfidenceMetrics;
  issues: ValidationIssue[];
  uncertainties: UncertaintyFlag[];
  codeValidation?: CodeValidationResult;
  recommendations: string[];
  nextSteps: string[];
}

class ContentAccuracyValidator {
  private projectContext: any;
  private tempDir: string;
  private executionSimulator: ExecutionSimulator | null = null;
  private useExecutionSimulation: boolean;

  constructor(useExecutionSimulation: boolean = true) {
    this.tempDir = path.join(currentDir, ".tmp");
    this.useExecutionSimulation = useExecutionSimulation;

    // Initialize execution simulator if enabled
    if (useExecutionSimulation) {
      this.executionSimulator = createExecutionSimulator({
        maxDepth: 5,
        maxSteps: 50,
        timeoutMs: 15000,
        detectNullRefs: true,
        detectTypeMismatches: true,
        detectUnreachableCode: true,
        confidenceThreshold: 0.6,
      });
    }
  }

  async validateContent(
    options: ValidationOptions,
    context?: any,
  ): Promise<ValidationResult> {
    if (context?.meta?.progressToken) {
      await context.meta.reportProgress?.({ progress: 0, total: 100 });
    }

    const result: ValidationResult = {
      success: false,
      confidence: this.initializeConfidenceMetrics(),
      issues: [],
      uncertainties: [],
      recommendations: [],
      nextSteps: [],
    };

    // Load project context if analysis ID provided
    if (options.analysisId) {
      await context?.info?.("📊 Loading project context...");
      this.projectContext = await this.loadProjectContext(options.analysisId);
    }

    if (context?.meta?.progressToken) {
      await context.meta.reportProgress?.({ progress: 20, total: 100 });
    }

    // Determine if we should analyze application code vs documentation
    await context?.info?.("🔎 Analyzing content type...");
    const isApplicationValidation = await this.shouldAnalyzeApplicationCode(
      options.contentPath,
    );

    if (context?.meta?.progressToken) {
      await context.meta.reportProgress?.({ progress: 40, total: 100 });
    }

    // Perform different types of validation based on request
    if (
      options.validationType === "all" ||
      options.validationType === "accuracy"
    ) {
      await this.validateAccuracy(options.contentPath, result);
    }

    if (
      options.validationType === "all" ||
      options.validationType === "completeness"
    ) {
      await this.validateCompleteness(options.contentPath, result);
    }

    if (
      options.validationType === "all" ||
      options.validationType === "compliance"
    ) {
      if (isApplicationValidation) {
        await this.validateApplicationStructureCompliance(
          options.contentPath,
          result,
        );
      } else {
        await this.validateDiataxisCompliance(options.contentPath, result);
      }
    }

    // Code validation if requested
    if (options.includeCodeValidation) {
      result.codeValidation = await this.validateCodeExamples(
        options.contentPath,
      );
      // Set code example relevance confidence based on code validation results
      if (result.codeValidation) {
        const successRate =
          result.codeValidation.exampleResults.length > 0
            ? result.codeValidation.exampleResults.filter(
                (e) => e.compilationSuccess,
              ).length / result.codeValidation.exampleResults.length
            : 1;
        result.confidence.breakdown.codeExampleRelevance = Math.round(
          successRate * 100,
        );
      }
    } else {
      // If code validation is skipped, assume reasonable confidence
      result.confidence.breakdown.codeExampleRelevance = 75;
    }

    // Set framework version accuracy based on technology detection confidence
    result.confidence.breakdown.frameworkVersionAccuracy = Math.min(
      90,
      result.confidence.breakdown.technologyDetection + 10,
    );

    // Set architectural assumptions confidence based on file structure and content analysis
    const filesAnalyzed = await this.getMarkdownFiles(options.contentPath);
    const hasStructuredContent = filesAnalyzed.length > 3; // Basic heuristic
    result.confidence.breakdown.architecturalAssumptions = hasStructuredContent
      ? 80
      : 60;

    // Calculate overall confidence and success
    this.calculateOverallMetrics(result);

    // Generate recommendations and next steps
    this.generateRecommendations(result, options);

    if (context?.meta?.progressToken) {
      await context.meta.reportProgress?.({ progress: 100, total: 100 });
    }

    const status = result.success ? "PASSED" : "ISSUES FOUND";
    await context?.info?.(
      `✅ Validation complete! Status: ${status} (${result.confidence.overall}% confidence, ${result.issues.length} issue(s))`,
    );

    return result;
  }

  private initializeConfidenceMetrics(): ConfidenceMetrics {
    return {
      overall: 0,
      breakdown: {
        technologyDetection: 0,
        frameworkVersionAccuracy: 0,
        codeExampleRelevance: 0,
        architecturalAssumptions: 0,
        businessContextAlignment: 0,
      },
      riskFactors: [],
    };
  }

  private async loadProjectContext(analysisId: string): Promise<any> {
    // Try to get analysis from memory system first
    try {
      const memoryRecall = await handleMemoryRecall({
        query: analysisId,
        type: "analysis",
        limit: 1,
      });

      // Handle the memory recall result structure
      if (
        memoryRecall &&
        memoryRecall.memories &&
        memoryRecall.memories.length > 0
      ) {
        const memory = memoryRecall.memories[0];

        // Handle wrapped content structure
        if (
          memory.data &&
          memory.data.content &&
          Array.isArray(memory.data.content)
        ) {
          // Extract the JSON from the first text content
          const firstContent = memory.data.content[0];
          if (
            firstContent &&
            firstContent.type === "text" &&
            firstContent.text
          ) {
            try {
              return JSON.parse(firstContent.text);
            } catch (parseError) {
              console.warn(
                "Failed to parse analysis content from memory:",
                parseError,
              );
            }
          }
        }

        // Try direct content or data access
        if (memory.content) {
          return memory.content;
        }
        if (memory.data) {
          return memory.data;
        }
      }
    } catch (error) {
      console.warn("Failed to retrieve from memory system:", error);
    }

    // Fallback to reading from cached analysis file
    try {
      const analysisPath = path.join(
        ".documcp",
        "analyses",
        `${analysisId}.json`,
      );
      const content = await fs.readFile(analysisPath, "utf-8");
      return JSON.parse(content);
    } catch {
      // Return default context if no analysis found
      return {
        metadata: { projectName: "unknown", primaryLanguage: "JavaScript" },
        technologies: {},
        dependencies: { packages: [] },
      };
    }
  }

  private async validateAccuracy(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    const files = await this.getMarkdownFiles(contentPath);

    for (const file of files) {
      const content = await fs.readFile(file, "utf-8");

      // Check for common accuracy issues
      await this.checkTechnicalAccuracy(file, content, result);
      await this.checkFrameworkVersionCompatibility(file, content, result);
      await this.checkCommandAccuracy(file, content, result);
      await this.checkLinkValidity(file, content, result);
    }

    // Update confidence based on findings
    this.updateAccuracyConfidence(result);
  }

  private async checkTechnicalAccuracy(
    filePath: string,
    content: string,
    result: ValidationResult,
  ): Promise<void> {
    // Check for deprecated patterns
    const deprecatedPatterns = [
      {
        pattern: /npm install -g/,
        suggestion: "Use npx instead of global installs",
      },
      { pattern: /var\s+\w+/, suggestion: "Use const or let instead of var" },
      { pattern: /function\(\)/, suggestion: "Consider using arrow functions" },
      { pattern: /http:\/\//, suggestion: "Use HTTPS URLs for security" },
    ];

    for (const { pattern, suggestion } of deprecatedPatterns) {
      if (pattern.test(content)) {
        result.issues.push({
          type: "warning",
          category: "accuracy",
          location: { file: path.basename(filePath) },
          description: `Potentially outdated pattern detected: ${pattern.source}`,
          evidence: [content.match(pattern)?.[0] || ""],
          suggestedFix: suggestion,
          confidence: 80,
        });
      }
    }

    // Check for missing error handling in code examples
    const codeBlocks = this.extractCodeBlocks(content);
    for (const block of codeBlocks) {
      if (block.language === "javascript" || block.language === "typescript") {
        if (
          block.code.includes("await") &&
          !block.code.includes("try") &&
          !block.code.includes("catch")
        ) {
          result.issues.push({
            type: "warning",
            category: "accuracy",
            location: { file: path.basename(filePath) },
            description: "Async code without error handling",
            evidence: [block.code.substring(0, 100)],
            suggestedFix: "Add try-catch blocks for async operations",
            confidence: 90,
          });
        }
      }
    }
  }

  private async checkFrameworkVersionCompatibility(
    filePath: string,
    content: string,
    result: ValidationResult,
  ): Promise<void> {
    if (!this.projectContext) return;

    // Check if mentioned versions align with project dependencies
    const versionPattern = /@(\d+\.\d+\.\d+)/g;
    const matches = content.match(versionPattern);

    if (matches) {
      for (const match of matches) {
        const version = match.replace("@", "");

        result.uncertainties.push({
          area: "version-compatibility",
          severity: "medium",
          description: `Version ${version} mentioned in documentation`,
          potentialImpact: "May not match actual project dependencies",
          clarificationNeeded: "Verify version compatibility with project",
          fallbackStrategy: "Use generic version-agnostic examples",
        });
      }
    }
  }

  private async checkCommandAccuracy(
    filePath: string,
    content: string,
    result: ValidationResult,
  ): Promise<void> {
    const codeBlocks = this.extractCodeBlocks(content);

    for (const block of codeBlocks) {
      if (block.language === "bash" || block.language === "sh") {
        // Check for common command issues
        const commands = block.code
          .split("\n")
          .filter((line) => line.trim() && !line.startsWith("#"));

        for (const command of commands) {
          // Check for potentially dangerous commands
          const dangerousPatterns = [
            /rm -rf \//,
            /sudo rm/,
            /chmod 777/,
            /> \/dev\/null 2>&1/,
          ];

          for (const pattern of dangerousPatterns) {
            if (pattern.test(command)) {
              result.issues.push({
                type: "error",
                category: "accuracy",
                location: { file: path.basename(filePath) },
                description: "Potentially dangerous command in documentation",
                evidence: [command],
                suggestedFix: "Review and provide safer alternative",
                confidence: 95,
              });
            }
          }

          // Check for non-portable commands (Windows vs Unix)
          if (command.includes("\\") && command.includes("/")) {
            result.issues.push({
              type: "warning",
              category: "accuracy",
              location: { file: path.basename(filePath) },
              description: "Mixed path separators in command",
              evidence: [command],
              suggestedFix:
                "Use consistent path separators or provide OS-specific examples",
              confidence: 85,
            });
          }
        }
      }
    }
  }

  private async checkLinkValidity(
    filePath: string,
    content: string,
    result: ValidationResult,
  ): Promise<void> {
    const linkPattern = /\[([^\]]+)\]\(([^)]+)\)/g;
    const links: Array<{ text: string; url: string }> = [];
    let match;

    while ((match = linkPattern.exec(content)) !== null) {
      links.push({ text: match[1], url: match[2] });
    }

    for (const link of links) {
      // Check internal links
      if (!link.url.startsWith("http")) {
        const targetPath = path.resolve(path.dirname(filePath), link.url);
        try {
          await fs.access(targetPath);
        } catch {
          result.issues.push({
            type: "error",
            category: "accuracy",
            location: { file: path.basename(filePath) },
            description: `Broken internal link: ${link.url}`,
            evidence: [link.text],
            suggestedFix: "Fix the link path or create the missing file",
            confidence: 100,
          });
        }
      }

      // Flag external links for manual verification
      if (link.url.startsWith("http")) {
        result.uncertainties.push({
          area: "external-links",
          severity: "low",
          description: `External link: ${link.url}`,
          potentialImpact: "Link may become outdated or broken",
          clarificationNeeded: "Verify link is still valid",
          fallbackStrategy: "Archive important external content locally",
        });
      }
    }
  }

  private async validateCompleteness(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    const files = await this.getMarkdownFiles(contentPath);
    const structure = await this.analyzeDiataxisStructure(contentPath);

    // Check for missing essential sections
    const requiredSections = [
      "tutorials",
      "how-to",
      "reference",
      "explanation",
    ];
    const missingSections = requiredSections.filter(
      (section) => !structure.sections.includes(section),
    );

    if (missingSections.length > 0) {
      result.issues.push({
        type: "warning",
        category: "completeness",
        location: { file: "documentation structure" },
        description: `Missing Diataxis sections: ${missingSections.join(", ")}`,
        evidence: structure.sections,
        suggestedFix:
          "Add missing Diataxis sections for complete documentation",
        confidence: 100,
      });
    }

    // Check content depth in each section
    for (const section of structure.sections) {
      const sectionFiles = files.filter((f) => f.includes(`/${section}/`));
      if (sectionFiles.length < 2) {
        result.issues.push({
          type: "info",
          category: "completeness",
          location: { file: section },
          description: `Limited content in ${section} section`,
          evidence: [`Only ${sectionFiles.length} files`],
          suggestedFix: "Consider adding more comprehensive coverage",
          confidence: 75,
        });
      }
    }

    // Update completeness confidence
    result.confidence.breakdown.businessContextAlignment = Math.max(
      0,
      100 - missingSections.length * 25,
    );
  }

  private async validateDiataxisCompliance(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    const files = await this.getMarkdownFiles(contentPath);

    for (const file of files) {
      const content = await fs.readFile(file, "utf-8");
      const section = this.identifyDiataxisSection(file);

      if (section) {
        await this.checkSectionCompliance(file, content, section, result);
      }
    }
  }

  private async validateApplicationStructureCompliance(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    // Analyze application source code for Diataxis compliance
    await this.validateSourceCodeDocumentation(contentPath, result);
    await this.validateApplicationArchitecture(contentPath, result);
    await this.validateInlineDocumentationPatterns(contentPath, result);
  }

  private async validateSourceCodeDocumentation(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    const sourceFiles = await this.getSourceFiles(contentPath);

    for (const file of sourceFiles) {
      const content = await fs.readFile(file, "utf-8");

      // Check for proper JSDoc/TSDoc documentation
      await this.checkInlineDocumentationQuality(file, content, result);

      // Check for README files and their structure
      if (file.endsWith("README.md")) {
        await this.validateReadmeStructure(file, content, result);
      }

      // Check for proper module/class documentation
      await this.checkModuleDocumentation(file, content, result);
    }
  }

  private async validateApplicationArchitecture(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    // Check if the application structure supports different types of documentation
    const hasToolsDir = await this.pathExists(path.join(contentPath, "tools"));
    const hasTypesDir = await this.pathExists(path.join(contentPath, "types"));
    // Check for workflows directory (currently not used but may be useful for future validation)
    // const hasWorkflowsDir = await this.pathExists(path.join(contentPath, 'workflows'));

    if (!hasToolsDir) {
      result.issues.push({
        type: "warning",
        category: "compliance",
        location: { file: "application structure" },
        description:
          "No dedicated tools directory found - may impact reference documentation organization",
        evidence: ["Missing /tools directory"],
        suggestedFix:
          "Organize tools into dedicated directory for better reference documentation",
        confidence: 80,
      });
    }

    if (!hasTypesDir) {
      result.issues.push({
        type: "info",
        category: "compliance",
        location: { file: "application structure" },
        description:
          "No types directory found - may impact API reference documentation",
        evidence: ["Missing /types directory"],
        suggestedFix: "Consider organizing types for better API documentation",
        confidence: 70,
      });
    }
  }

  private async validateInlineDocumentationPatterns(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    const sourceFiles = await this.getSourceFiles(contentPath);

    for (const file of sourceFiles) {
      const content = await fs.readFile(file, "utf-8");

      // Check for proper function documentation that could support tutorials
      const functions = this.extractFunctions(content);
      for (const func of functions) {
        if (func.isExported && !func.hasDocumentation) {
          result.issues.push({
            type: "warning",
            category: "compliance",
            location: { file: path.basename(file), line: func.line },
            description: `Exported function '${func.name}' lacks documentation`,
            evidence: [func.signature],
            suggestedFix:
              "Add JSDoc/TSDoc documentation to support tutorial and reference content",
            confidence: 85,
          });
        }
      }

      // Check for proper error handling documentation
      const errorPatterns = content.match(/throw new \w*Error/g);
      if (errorPatterns && errorPatterns.length > 0) {
        const hasErrorDocs =
          content.includes("@throws") || content.includes("@error");
        if (!hasErrorDocs) {
          result.issues.push({
            type: "info",
            category: "compliance",
            location: { file: path.basename(file) },
            description:
              "Error throwing code found without error documentation",
            evidence: errorPatterns,
            suggestedFix:
              "Document error conditions to support troubleshooting guides",
            confidence: 75,
          });
        }
      }
    }
  }

  private identifyDiataxisSection(filePath: string): string | null {
    const sections = ["tutorials", "how-to", "reference", "explanation"];

    for (const section of sections) {
      if (filePath.includes(`/${section}/`)) {
        return section;
      }
    }

    return null;
  }

  private async checkSectionCompliance(
    filePath: string,
    content: string,
    section: string,
    result: ValidationResult,
  ): Promise<void> {
    const complianceRules = this.getDiataxisComplianceRules(section);

    for (const rule of complianceRules) {
      if (!rule.check(content)) {
        result.issues.push({
          type: "warning",
          category: "compliance",
          location: { file: path.basename(filePath), section },
          description: rule.message,
          evidence: [rule.evidence?.(content) || ""],
          suggestedFix: rule.fix,
          confidence: rule.confidence,
        });
      }
    }
  }

  private getDiataxisComplianceRules(section: string) {
    const rules: any = {
      tutorials: [
        {
          check: (content: string) =>
            content.includes("## Prerequisites") ||
            content.includes("## Requirements"),
          message: "Tutorial should include prerequisites section",
          fix: "Add a prerequisites or requirements section",
          confidence: 90,
        },
        {
          check: (content: string) => /step|Step|STEP/.test(content),
          message: "Tutorial should be organized in clear steps",
          fix: "Structure content with numbered steps or clear progression",
          confidence: 85,
        },
        {
          check: (content: string) => content.includes("```"),
          message: "Tutorial should include practical code examples",
          fix: "Add code blocks with working examples",
          confidence: 80,
        },
      ],
      "how-to": [
        {
          check: (content: string) => /how to|How to|HOW TO/.test(content),
          message: "How-to guide should focus on specific tasks",
          fix: "Frame content around achieving specific goals",
          confidence: 75,
        },
        {
          check: (content: string) => content.length > 500,
          message: "How-to guide should provide detailed guidance",
          fix: "Expand with more detailed instructions",
          confidence: 70,
        },
      ],
      reference: [
        {
          check: (content: string) => /##|###/.test(content),
          message: "Reference should be well-structured with clear sections",
          fix: "Add proper headings and organization",
          confidence: 95,
        },
        {
          check: (content: string) => /\|.*\|/.test(content),
          message: "Reference should include tables for structured information",
          fix: "Consider using tables for parameters, options, etc.",
          confidence: 60,
        },
      ],
      explanation: [
        {
          check: (content: string) =>
            content.includes("why") || content.includes("Why"),
          message: 'Explanation should address the "why" behind concepts',
          fix: "Include rationale and context for decisions/concepts",
          confidence: 80,
        },
        {
          check: (content: string) => content.length > 800,
          message: "Explanation should provide in-depth coverage",
          fix: "Expand with more comprehensive explanation",
          confidence: 70,
        },
      ],
    };

    return rules[section] || [];
  }

  private async validateCodeExamples(
    contentPath: string,
  ): Promise<CodeValidationResult> {
    const files = await this.getMarkdownFiles(contentPath);
    const allExamples: ExampleValidation[] = [];

    for (const file of files) {
      const content = await fs.readFile(file, "utf-8");
      const codeBlocks = this.extractCodeBlocks(content);

      for (const block of codeBlocks) {
        if (this.isValidatableLanguage(block.language)) {
          const validation = await this.validateCodeBlock(block, file);
          allExamples.push(validation);
        }
      }
    }

    return {
      overallSuccess: allExamples.every((e) => e.compilationSuccess),
      exampleResults: allExamples,
      confidence: this.calculateCodeValidationConfidence(allExamples),
    };
  }

  private extractCodeBlocks(
    content: string,
  ): Array<{ language: string; code: string; id: string }> {
    const codeBlockPattern = /```(\w+)?\n([\s\S]*?)```/g;
    const blocks: Array<{ language: string; code: string; id: string }> = [];
    let match;
    let index = 0;

    while ((match = codeBlockPattern.exec(content)) !== null) {
      blocks.push({
        language: match[1] || "text",
        code: match[2].trim(),
        id: `block-${index++}`,
      });
    }

    return blocks;
  }

  private isValidatableLanguage(language: string): boolean {
    const validatable = [
      "javascript",
      "typescript",
      "js",
      "ts",
      "json",
      "bash",
      "sh",
    ];
    return validatable.includes(language.toLowerCase());
  }

  private async validateCodeBlock(
    block: { language: string; code: string; id: string },
    filePath: string,
  ): Promise<ExampleValidation> {
    const validation: ExampleValidation = {
      example: block.id,
      compilationSuccess: false,
      executionSuccess: false,
      issues: [],
      confidence: 0,
    };

    try {
      if (block.language === "typescript" || block.language === "ts") {
        await this.validateTypeScriptCode(block.code, validation);

        // Use execution simulation for additional validation if available
        if (
          this.useExecutionSimulation &&
          this.executionSimulator &&
          validation.compilationSuccess
        ) {
          await this.enhanceWithExecutionSimulation(
            block.code,
            validation,
            filePath,
          );
        }
      } else if (block.language === "javascript" || block.language === "js") {
        await this.validateJavaScriptCode(block.code, validation);

        // Use execution simulation for additional validation if available
        if (
          this.useExecutionSimulation &&
          this.executionSimulator &&
          validation.compilationSuccess
        ) {
          await this.enhanceWithExecutionSimulation(
            block.code,
            validation,
            filePath,
          );
        }
      } else if (block.language === "json") {
        await this.validateJSONCode(block.code, validation);
      } else if (block.language === "bash" || block.language === "sh") {
        await this.validateBashCode(block.code, validation);
      }
    } catch (error: any) {
      validation.issues.push({
        type: "error",
        category: "accuracy",
        location: { file: path.basename(filePath) },
        description: `Code validation failed: ${error.message}`,
        evidence: [block.code.substring(0, 100)],
        suggestedFix: "Review and fix syntax errors",
        confidence: 95,
      });
    }

    return validation;
  }

  /**
   * Enhance validation with execution simulation results
   */
  private async enhanceWithExecutionSimulation(
    code: string,
    validation: ExampleValidation,
    filePath: string,
  ): Promise<void> {
    if (!this.executionSimulator) return;

    try {
      const simResult = await this.executionSimulator.validateExample(
        code,
        code,
      );

      // Add simulation-detected issues to validation
      for (const issue of simResult.issues) {
        validation.issues.push({
          type: issue.severity === "error" ? "error" : "warning",
          category: "accuracy",
          location: {
            file: path.basename(filePath),
            line: issue.location.line,
          },
          description: `[Simulation] ${issue.description}`,
          evidence: [issue.codeSnippet || ""],
          suggestedFix: issue.suggestion,
          confidence: Math.round(simResult.trace.confidenceScore * 100),
        });
      }

      // Update execution success based on simulation
      validation.executionSuccess = simResult.isValid;

      // Adjust confidence based on simulation confidence
      if (simResult.trace.confidenceScore > 0) {
        validation.confidence = Math.round(
          (validation.confidence + simResult.trace.confidenceScore * 100) / 2,
        );
      }
    } catch (error) {
      // Simulation is best-effort, don't fail validation on simulation errors
      console.warn("Execution simulation failed:", error);
    }
  }

  private async validateTypeScriptCode(
    code: string,
    validation: ExampleValidation,
  ): Promise<void> {
    // Ensure temp directory exists
    await fs.mkdir(this.tempDir, { recursive: true });

    const tempFile = path.join(this.tempDir, `temp-${Date.now()}.ts`);

    try {
      // Write code to temporary file
      await fs.writeFile(tempFile, code, "utf-8");

      // Try to compile with TypeScript
      const { stderr } = await execAsync(
        `npx tsc --noEmit --skipLibCheck ${tempFile}`,
      );

      if (stderr && stderr.includes("error")) {
        validation.issues.push({
          type: "error",
          category: "accuracy",
          location: { file: "code-example" },
          description: "TypeScript compilation error",
          evidence: [stderr],
          suggestedFix: "Fix TypeScript syntax and type errors",
          confidence: 90,
        });
      } else {
        validation.compilationSuccess = true;
        validation.confidence = 85;
      }
    } catch (error: any) {
      if (error.stderr && error.stderr.includes("error")) {
        validation.issues.push({
          type: "error",
          category: "accuracy",
          location: { file: "code-example" },
          description: "TypeScript compilation failed",
          evidence: [error.stderr],
          suggestedFix: "Fix compilation errors",
          confidence: 95,
        });
      }
    } finally {
      // Clean up temp file
      try {
        await fs.unlink(tempFile);
      } catch {
        // Ignore cleanup errors
      }
    }
  }

  private async validateJavaScriptCode(
    code: string,
    validation: ExampleValidation,
  ): Promise<void> {
    try {
      // Basic syntax check using Node.js
      new Function(code);
      validation.compilationSuccess = true;
      validation.confidence = 75;
    } catch (error: any) {
      validation.issues.push({
        type: "error",
        category: "accuracy",
        location: { file: "code-example" },
        description: `JavaScript syntax error: ${error.message}`,
        evidence: [code.substring(0, 100)],
        suggestedFix: "Fix JavaScript syntax errors",
        confidence: 90,
      });
    }
  }

  private async validateJSONCode(
    code: string,
    validation: ExampleValidation,
  ): Promise<void> {
    try {
      JSON.parse(code);
      validation.compilationSuccess = true;
      validation.confidence = 95;
    } catch (error: any) {
      validation.issues.push({
        type: "error",
        category: "accuracy",
        location: { file: "code-example" },
        description: `Invalid JSON: ${error.message}`,
        evidence: [code.substring(0, 100)],
        suggestedFix: "Fix JSON syntax errors",
        confidence: 100,
      });
    }
  }

  private async validateBashCode(
    code: string,
    validation: ExampleValidation,
  ): Promise<void> {
    // Basic bash syntax validation
    const lines = code
      .split("\n")
      .filter((line) => line.trim() && !line.startsWith("#"));

    for (const line of lines) {
      // Check for basic syntax issues
      if (line.includes("&&") && line.includes("||")) {
        validation.issues.push({
          type: "warning",
          category: "accuracy",
          location: { file: "code-example" },
          description: "Complex command chaining may be confusing",
          evidence: [line],
          suggestedFix:
            "Consider breaking into separate commands or adding explanation",
          confidence: 60,
        });
      }

      // Check for unquoted variables in dangerous contexts
      if (line.includes("rm") && /\$\w+/.test(line) && !/'.*\$.*'/.test(line)) {
        validation.issues.push({
          type: "warning",
          category: "accuracy",
          location: { file: "code-example" },
          description: "Unquoted variable in potentially dangerous command",
          evidence: [line],
          suggestedFix: "Quote variables to prevent word splitting",
          confidence: 80,
        });
      }
    }

    validation.compilationSuccess =
      validation.issues.filter((i) => i.type === "error").length === 0;
    validation.confidence = validation.compilationSuccess ? 70 : 20;
  }

  private calculateCodeValidationConfidence(
    examples: ExampleValidation[],
  ): number {
    if (examples.length === 0) return 0;

    const totalConfidence = examples.reduce(
      (sum, ex) => sum + ex.confidence,
      0,
    );
    return Math.round(totalConfidence / examples.length);
  }

  public async getMarkdownFiles(
    contentPath: string,
    maxDepth: number = 5,
  ): Promise<string[]> {
    const files: string[] = [];
    const excludedDirs = new Set([
      "node_modules",
      ".git",
      "dist",
      "build",
      ".next",
      ".nuxt",
      "coverage",
      ".tmp",
      "tmp",
      ".cache",
      ".vscode",
      ".idea",
      "logs",
      ".logs",
      ".npm",
      ".yarn",
    ]);

    const scan = async (
      dir: string,
      currentDepth: number = 0,
    ): Promise<void> => {
      if (currentDepth > maxDepth) return;

      try {
        const entries = await fs.readdir(dir, { withFileTypes: true });

        for (const entry of entries) {
          const fullPath = path.join(dir, entry.name);

          if (entry.isDirectory()) {
            // Skip excluded directories
            if (excludedDirs.has(entry.name) || entry.name.startsWith(".")) {
              continue;
            }

            // Prevent symlink loops
            try {
              const stats = await fs.lstat(fullPath);
              if (stats.isSymbolicLink()) {
                continue;
              }
            } catch {
              continue;
            }

            await scan(fullPath, currentDepth + 1);
          } else if (entry.name.endsWith(".md")) {
            files.push(fullPath);

            // Limit total files to prevent memory issues
            if (files.length > 500) {
              console.warn("Markdown file limit reached (500), stopping scan");
              return;
            }
          }
        }
      } catch (error) {
        // Skip directories that can't be read
        console.warn(`Warning: Could not read directory ${dir}:`, error);
      }
    };

    try {
      await scan(contentPath);
    } catch (error) {
      console.warn("Error scanning directory:", error);
    }

    return files;
  }

  private async getSourceFiles(
    contentPath: string,
    maxDepth: number = 5,
  ): Promise<string[]> {
    const files: string[] = [];
    const excludedDirs = new Set([
      "node_modules",
      ".git",
      "dist",
      "build",
      ".next",
      ".nuxt",
      "coverage",
      ".tmp",
      "tmp",
      ".cache",
      ".vscode",
      ".idea",
      "logs",
      ".logs",
      ".npm",
      ".yarn",
    ]);

    const scan = async (
      dir: string,
      currentDepth: number = 0,
    ): Promise<void> => {
      if (currentDepth > maxDepth) return;

      try {
        const entries = await fs.readdir(dir, { withFileTypes: true });

        for (const entry of entries) {
          const fullPath = path.join(dir, entry.name);

          if (entry.isDirectory()) {
            // Skip excluded directories
            if (excludedDirs.has(entry.name) || entry.name.startsWith(".")) {
              continue;
            }

            // Prevent symlink loops
            try {
              const stats = await fs.lstat(fullPath);
              if (stats.isSymbolicLink()) {
                continue;
              }
            } catch {
              continue;
            }

            await scan(fullPath, currentDepth + 1);
          } else if (
            entry.name.endsWith(".ts") ||
            entry.name.endsWith(".js") ||
            entry.name.endsWith(".md")
          ) {
            files.push(fullPath);

            // Limit total files to prevent memory issues
            if (files.length > 1000) {
              console.warn("File limit reached (1000), stopping scan");
              return;
            }
          }
        }
      } catch (error) {
        // Skip directories that can't be read
        console.warn(`Warning: Could not read directory ${dir}:`, error);
      }
    };

    try {
      await scan(contentPath);
    } catch (error) {
      console.warn("Error scanning directory:", error);
    }

    return files;
  }

  private async pathExists(filePath: string): Promise<boolean> {
    try {
      await fs.access(filePath);
      return true;
    } catch {
      return false;
    }
  }

  private extractFunctions(content: string): Array<{
    name: string;
    line: number;
    signature: string;
    isExported: boolean;
    hasDocumentation: boolean;
  }> {
    const functions: Array<{
      name: string;
      line: number;
      signature: string;
      isExported: boolean;
      hasDocumentation: boolean;
    }> = [];
    const lines = content.split("\n");

    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];

      // Match function declarations and exports
      const functionMatch = line.match(
        /^(export\s+)?(async\s+)?function\s+(\w+)/,
      );
      const arrowMatch = line.match(
        /^(export\s+)?(?:const|let|var)\s+(\w+)\s*=\s*(async\s+)?\(/,
      );

      if (functionMatch) {
        const name = functionMatch[3];
        const isExported = !!functionMatch[1];
        const hasDocumentation = this.checkForDocumentation(lines, i);

        functions.push({
          name,
          line: i + 1,
          signature: line.trim(),
          isExported,
          hasDocumentation,
        });
      } else if (arrowMatch) {
        const name = arrowMatch[2];
        const isExported = !!arrowMatch[1];
        const hasDocumentation = this.checkForDocumentation(lines, i);

        functions.push({
          name,
          line: i + 1,
          signature: line.trim(),
          isExported,
          hasDocumentation,
        });
      }
    }

    return functions;
  }

  private async checkInlineDocumentationQuality(
    _file: string,
    _content: string,
    _result: ValidationResult,
  ): Promise<void> {
    // Implementation for checking JSDoc/TSDoc quality
    // This could check for proper parameter documentation, return types, etc.
  }

  private async validateReadmeStructure(
    _file: string,
    content: string,
    result: ValidationResult,
  ): Promise<void> {
    // Check if README follows good structure
    const hasTitle = /^#\s+/.test(content);
    const hasDescription =
      content.includes("## Description") || content.includes("## Overview");
    const hasInstallation =
      content.includes("## Installation") || content.includes("## Setup");
    const hasUsage =
      content.includes("## Usage") || content.includes("## Getting Started");

    if (!hasTitle) {
      result.issues.push({
        type: "warning",
        category: "compliance",
        location: { file: "README.md" },
        description: "README missing clear title",
        evidence: ["No H1 heading found"],
        suggestedFix: "Add clear title with # heading",
        confidence: 90,
      });
    }

    if (!hasDescription && !hasInstallation && !hasUsage) {
      result.issues.push({
        type: "warning",
        category: "compliance",
        location: { file: "README.md" },
        description:
          "README lacks essential sections (description, installation, usage)",
        evidence: ["Missing standard README sections"],
        suggestedFix:
          "Add sections for description, installation, and usage following Diataxis principles",
        confidence: 85,
      });
    }
  }

  private async checkModuleDocumentation(
    _file: string,
    _content: string,
    _result: ValidationResult,
  ): Promise<void> {
    // Implementation for checking module-level documentation
    // This could check for file-level JSDoc, proper exports documentation, etc.
  }

  private checkForDocumentation(
    lines: string[],
    functionLineIndex: number,
  ): boolean {
    // Look backwards from the function line to find documentation
    let checkIndex = functionLineIndex - 1;

    // Skip empty lines
    while (checkIndex >= 0 && lines[checkIndex].trim() === "") {
      checkIndex--;
    }

    // Check if we found the end of a JSDoc comment
    if (checkIndex >= 0 && lines[checkIndex].trim() === "*/") {
      // Look backwards to find the start of the JSDoc block
      let jsDocStart = checkIndex;
      while (jsDocStart >= 0) {
        const line = lines[jsDocStart].trim();
        if (line.startsWith("/**")) {
          return true; // Found complete JSDoc block
        }
        if (!line.startsWith("*") && line !== "*/") {
          break; // Not part of JSDoc block
        }
        jsDocStart--;
      }
    }

    // Also check for single-line JSDoc comments
    if (
      checkIndex >= 0 &&
      lines[checkIndex].trim().startsWith("/**") &&
      lines[checkIndex].includes("*/")
    ) {
      return true;
    }

    return false;
  }

  private async shouldAnalyzeApplicationCode(
    contentPath: string,
  ): Promise<boolean> {
    // Check if the path contains application source code vs documentation
    const hasSrcDir = await this.pathExists(path.join(contentPath, "src"));
    const hasPackageJson = await this.pathExists(
      path.join(contentPath, "package.json"),
    );
    const hasTypescriptFiles = (await this.getSourceFiles(contentPath)).some(
      (file) => file.endsWith(".ts"),
    );

    // If path ends with 'src' or is a project root with src/, analyze as application code
    if (
      contentPath.endsWith("/src") ||
      contentPath.endsWith("\\src") ||
      (hasSrcDir && hasPackageJson)
    ) {
      return true;
    }

    // If path contains TypeScript/JavaScript files and package.json, treat as application code
    if (hasTypescriptFiles && hasPackageJson) {
      return true;
    }

    // If path is specifically a documentation directory, analyze as documentation
    if (contentPath.includes("/docs") || contentPath.includes("\\docs")) {
      return false;
    }

    return false;
  }

  private async analyzeDiataxisStructure(
    contentPath: string,
  ): Promise<{ sections: string[] }> {
    const sections: string[] = [];

    try {
      const entries = await fs.readdir(contentPath, { withFileTypes: true });

      for (const entry of entries) {
        if (entry.isDirectory()) {
          const dirName = entry.name;
          if (
            ["tutorials", "how-to", "reference", "explanation"].includes(
              dirName,
            )
          ) {
            sections.push(dirName);
          }
        }
      }
    } catch {
      // Directory doesn't exist
    }

    return { sections };
  }

  private updateAccuracyConfidence(result: ValidationResult): void {
    const errorCount = result.issues.filter((i) => i.type === "error").length;
    const warningCount = result.issues.filter(
      (i) => i.type === "warning",
    ).length;

    // Base confidence starts high and decreases with issues
    let confidence = 95;
    confidence -= errorCount * 20;
    confidence -= warningCount * 5;
    confidence = Math.max(0, confidence);

    result.confidence.breakdown.technologyDetection = confidence;
  }

  private calculateOverallMetrics(result: ValidationResult): void {
    const breakdown = result.confidence.breakdown;
    const values = Object.values(breakdown).filter((v) => v > 0);

    if (values.length > 0) {
      result.confidence.overall = Math.round(
        values.reduce((a, b) => a + b, 0) / values.length,
      );
    }

    // Determine overall success
    const criticalIssues = result.issues.filter(
      (i) => i.type === "error",
    ).length;
    result.success = criticalIssues === 0;

    // Add risk factors based on issues
    if (criticalIssues > 0) {
      result.confidence.riskFactors.push({
        type: "high",
        category: "accuracy",
        description: `${criticalIssues} critical accuracy issues found`,
        impact: "Users may encounter broken examples or incorrect information",
        mitigation: "Fix all critical issues before publication",
      });
    }

    const uncertaintyCount = result.uncertainties.length;
    if (uncertaintyCount > 5) {
      result.confidence.riskFactors.push({
        type: "medium",
        category: "completeness",
        description: `${uncertaintyCount} areas requiring clarification`,
        impact: "Documentation may lack specificity for user context",
        mitigation: "Address high-priority uncertainties with user input",
      });
    }
  }

  private generateRecommendations(
    result: ValidationResult,
    _options: ValidationOptions,
  ): void {
    const recommendations: string[] = [];
    const nextSteps: string[] = [];

    // Generate recommendations based on issues found
    const errorCount = result.issues.filter((i) => i.type === "error").length;
    if (errorCount > 0) {
      recommendations.push(
        `Fix ${errorCount} critical accuracy issues before publication`,
      );
      nextSteps.push("Review and resolve all error-level validation issues");
    }

    const warningCount = result.issues.filter(
      (i) => i.type === "warning",
    ).length;
    if (warningCount > 0) {
      recommendations.push(
        `Address ${warningCount} potential accuracy concerns`,
      );
      nextSteps.push(
        "Review warning-level issues and apply fixes where appropriate",
      );
    }

    const uncertaintyCount = result.uncertainties.filter(
      (u) => u.severity === "high" || u.severity === "critical",
    ).length;
    if (uncertaintyCount > 0) {
      recommendations.push(
        `Clarify ${uncertaintyCount} high-uncertainty areas`,
      );
      nextSteps.push("Gather user input on areas flagged for clarification");
    }

    // Code validation recommendations
    if (result.codeValidation && !result.codeValidation.overallSuccess) {
      recommendations.push(
        "Fix code examples that fail compilation or execution tests",
      );
      nextSteps.push(
        "Test all code examples in appropriate development environment",
      );
    }

    // Completeness recommendations
    const missingCompliance = result.issues.filter(
      (i) => i.category === "compliance",
    ).length;
    if (missingCompliance > 0) {
      recommendations.push(
        "Improve Diataxis framework compliance for better user experience",
      );
      nextSteps.push(
        "Restructure content to better align with Diataxis principles",
      );
    }

    // General recommendations based on confidence level
    if (result.confidence.overall < 70) {
      recommendations.push(
        "Overall confidence is below recommended threshold - consider comprehensive review",
      );
      nextSteps.push(
        "Conduct manual review of generated content before publication",
      );
    }

    if (recommendations.length === 0) {
      recommendations.push("Content validation passed - ready for publication");
      nextSteps.push("Deploy documentation and monitor for user feedback");
    }

    result.recommendations = recommendations;
    result.nextSteps = nextSteps;
  }
}

export const validateDiataxisContent: Tool = {
  name: "validate_diataxis_content",
  description:
    "Validate the accuracy, completeness, and compliance of generated Diataxis documentation",
  inputSchema: {
    type: "object",
    properties: {
      contentPath: {
        type: "string",
        description: "Path to the documentation directory to validate",
      },
      analysisId: {
        type: "string",
        description:
          "Optional repository analysis ID for context-aware validation",
      },
      validationType: {
        type: "string",
        enum: ["accuracy", "completeness", "compliance", "all"],
        default: "all",
        description: "Type of validation to perform",
      },
      includeCodeValidation: {
        type: "boolean",
        default: true,
        description: "Whether to validate code examples for correctness",
      },
      confidence: {
        type: "string",
        enum: ["strict", "moderate", "permissive"],
        default: "moderate",
        description:
          "Validation confidence level - stricter levels catch more issues",
      },
    },
    required: ["contentPath"],
  },
};

/**
 * Validates Diataxis-compliant documentation content for accuracy, completeness, and compliance.
 *
 * Performs comprehensive validation of documentation content including accuracy verification,
 * completeness assessment, compliance checking, and code example validation. Uses advanced
 * confidence scoring and risk assessment to provide detailed validation results with
 * actionable recommendations.
 *
 * @param args - The validation parameters
 * @param args.contentPath - Path to the documentation content directory
 * @param args.analysisId - Optional repository analysis ID for context-aware validation
 * @param args.validationType - Type of validation to perform: "accuracy", "completeness", "compliance", or "all"
 * @param args.includeCodeValidation - Whether to validate code examples and syntax
 * @param args.confidence - Validation confidence level: "strict", "moderate", or "permissive"
 *
 * @returns Promise resolving to comprehensive validation results
 * @returns success - Whether validation passed overall
 * @returns confidence - Confidence metrics and risk assessment
 * @returns issues - Array of validation issues found
 * @returns uncertainties - Areas requiring clarification
 * @returns codeValidation - Code example validation results
 * @returns recommendations - Suggested improvements
 * @returns nextSteps - Recommended next actions
 *
 * @throws {Error} When content path is inaccessible
 * @throws {Error} When validation processing fails
 *
 * @example
 * ```typescript
 * // Comprehensive validation
 * const result = await handleValidateDiataxisContent({
 *   contentPath: "./docs",
 *   validationType: "all",
 *   includeCodeValidation: true,
 *   confidence: "moderate"
 * });
 *
 * console.log(`Validation success: ${result.success}`);
 * console.log(`Overall confidence: ${result.confidence.overall}%`);
 * console.log(`Issues found: ${result.issues.length}`);
 *
 * // Strict accuracy validation
 * const accuracy = await handleValidateDiataxisContent({
 *   contentPath: "./docs",
 *   validationType: "accuracy",
 *   confidence: "strict"
 * });
 * ```
 *
 * @since 1.0.0
 */
export async function handleValidateDiataxisContent(
  args: any,
  context?: any,
): Promise<ValidationResult> {
  await context?.info?.("🔍 Starting Diataxis content validation...");

  const validator = new ContentAccuracyValidator();

  // Add timeout protection to prevent infinite hangs
  const timeoutMs = 120000; // 2 minutes
  let timeoutHandle: NodeJS.Timeout;
  const timeoutPromise = new Promise<ValidationResult>((_, reject) => {
    timeoutHandle = setTimeout(() => {
      reject(
        new Error(
          `Validation timed out after ${
            timeoutMs / 1000
          } seconds. This may be due to a large directory structure. Try validating a smaller subset or specific directory.`,
        ),
      );
    }, timeoutMs);
  });

  const validationPromise = validator.validateContent(args, context);

  try {
    const result = await Promise.race([validationPromise, timeoutPromise]);
    clearTimeout(timeoutHandle!);
    return result;
  } catch (error: any) {
    clearTimeout(timeoutHandle!);
    // Return a partial result with error information
    return {
      success: false,
      confidence: {
        overall: 0,
        breakdown: {
          technologyDetection: 0,
          frameworkVersionAccuracy: 0,
          codeExampleRelevance: 0,
          architecturalAssumptions: 0,
          businessContextAlignment: 0,
        },
        riskFactors: [
          {
            type: "high",
            category: "validation",
            description: "Validation process failed or timed out",
            impact: "Unable to complete content validation",
            mitigation:
              "Try validating a smaller directory or specific subset of files",
          },
        ],
      },
      issues: [],
      uncertainties: [],
      recommendations: [
        "Validation failed or timed out",
        "Consider validating smaller directory subsets",
        "Check for very large files or deep directory structures",
        `Error: ${error.message}`,
      ],
      nextSteps: [
        "Verify the content path is correct and accessible",
        "Try validating specific subdirectories instead of the entire project",
        "Check for circular symlinks or very deep directory structures",
      ],
    };
  }
}

interface GeneralValidationResult {
  success: boolean;
  linksChecked: number;
  brokenLinks: string[];
  codeBlocksValidated: number;
  codeErrors: string[];
  recommendations: string[];
  summary: string;
}

export async function validateGeneralContent(
  args: any,
): Promise<GeneralValidationResult> {
  const {
    contentPath,
    validationType = "all",
    includeCodeValidation = true,
    followExternalLinks = false,
  } = args;

  const result: GeneralValidationResult = {
    success: true,
    linksChecked: 0,
    brokenLinks: [],
    codeBlocksValidated: 0,
    codeErrors: [],
    recommendations: [],
    summary: "",
  };

  try {
    // Get all markdown files
    const validator = new ContentAccuracyValidator();
    const files = await validator.getMarkdownFiles(contentPath);

    // Check links if requested
    if (validationType === "all" || validationType === "links") {
      for (const file of files) {
        const content = await fs.readFile(file, "utf-8");
        const links = extractLinksFromMarkdown(content);

        for (const link of links) {
          result.linksChecked++;

          // Skip external links unless explicitly requested
          if (link.startsWith("http") && !followExternalLinks) continue;

          // Check internal links
          if (!link.startsWith("http")) {
            const fullPath = path.resolve(path.dirname(file), link);
            try {
              await fs.access(fullPath);
            } catch {
              result.brokenLinks.push(`${path.basename(file)}: ${link}`);
              result.success = false;
            }
          }
        }
      }
    }

    // Validate code blocks if requested
    if (
      includeCodeValidation &&
      (validationType === "all" || validationType === "code")
    ) {
      for (const file of files) {
        const content = await fs.readFile(file, "utf-8");
        const codeBlocks = extractCodeBlocks(content);

        for (const block of codeBlocks) {
          result.codeBlocksValidated++;

          // Basic syntax validation
          if (block.language && block.code.trim()) {
            if (block.language === "javascript" || block.language === "js") {
              try {
                // Basic JS syntax check - look for common issues
                if (
                  block.code.includes("console.log") &&
                  !block.code.includes(";")
                ) {
                  result.codeErrors.push(
                    `${path.basename(file)}: Missing semicolon in JS code`,
                  );
                }
              } catch (error) {
                result.codeErrors.push(
                  `${path.basename(file)}: JS syntax error - ${error}`,
                );
                result.success = false;
              }
            }
          }
        }
      }
    }

    // Generate recommendations
    if (result.brokenLinks.length > 0) {
      result.recommendations.push(
        `Fix ${result.brokenLinks.length} broken internal links`,
      );
      result.recommendations.push(
        "Run documentation build to catch additional link issues",
      );
    }

    if (result.codeErrors.length > 0) {
      result.recommendations.push(
        `Review and fix ${result.codeErrors.length} code syntax issues`,
      );
    }

    if (result.success) {
      result.recommendations.push(
        "Content validation passed - no critical issues found",
      );
    }

    // Create summary
    result.summary = `Validated ${files.length} files, ${
      result.linksChecked
    } links, ${result.codeBlocksValidated} code blocks. ${
      result.success
        ? "PASSED"
        : `ISSUES FOUND: ${
            result.brokenLinks.length + result.codeErrors.length
          }`
    }`;

    return result;
  } catch (error) {
    result.success = false;
    result.recommendations.push(`Validation failed: ${error}`);
    result.summary = `Validation error: ${error}`;
    return result;
  }
}

// Helper function to extract links from markdown
function extractLinksFromMarkdown(content: string): string[] {
  const linkRegex = /\[([^\]]*)\]\(([^)]+)\)/g;
  const links: string[] = [];
  let match;

  while ((match = linkRegex.exec(content)) !== null) {
    links.push(match[2]); // The URL part
  }

  return links;
}

// Helper function to extract code blocks from markdown
function extractCodeBlocks(
  content: string,
): { language: string; code: string }[] {
  const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
  const blocks: { language: string; code: string }[] = [];
  let match;

  while ((match = codeBlockRegex.exec(content)) !== null) {
    blocks.push({
      language: match[1] || "text",
      code: match[2],
    });
  }

  return blocks;
}

```

--------------------------------------------------------------------------------
/src/utils/ast-analyzer.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * AST-based Code Analyzer (Phase 3)
 *
 * Uses tree-sitter parsers for multi-language AST analysis
 * Provides deep code structure extraction for drift detection
 */

import { parse as parseTypeScript } from "@typescript-eslint/typescript-estree";
import { promises as fs } from "fs";
import path from "path";
import crypto from "crypto";

// Language configuration
const LANGUAGE_CONFIGS: Record<
  string,
  { parser: string; extensions: string[] }
> = {
  typescript: { parser: "tree-sitter-typescript", extensions: [".ts", ".tsx"] },
  javascript: {
    parser: "tree-sitter-javascript",
    extensions: [".js", ".jsx", ".mjs"],
  },
  python: { parser: "tree-sitter-python", extensions: [".py"] },
  rust: { parser: "tree-sitter-rust", extensions: [".rs"] },
  go: { parser: "tree-sitter-go", extensions: [".go"] },
  java: { parser: "tree-sitter-java", extensions: [".java"] },
  ruby: { parser: "tree-sitter-ruby", extensions: [".rb"] },
  bash: { parser: "tree-sitter-bash", extensions: [".sh", ".bash"] },
};

export interface FunctionSignature {
  name: string;
  parameters: ParameterInfo[];
  returnType: string | null;
  isAsync: boolean;
  isExported: boolean;
  isPublic: boolean;
  docComment: string | null;
  startLine: number;
  endLine: number;
  complexity: number;
  dependencies: string[];
}

export interface ParameterInfo {
  name: string;
  type: string | null;
  optional: boolean;
  defaultValue: string | null;
}

export interface ClassInfo {
  name: string;
  isExported: boolean;
  extends: string | null;
  implements: string[];
  methods: FunctionSignature[];
  properties: PropertyInfo[];
  docComment: string | null;
  startLine: number;
  endLine: number;
}

export interface PropertyInfo {
  name: string;
  type: string | null;
  isStatic: boolean;
  isReadonly: boolean;
  visibility: "public" | "private" | "protected";
}

export interface InterfaceInfo {
  name: string;
  isExported: boolean;
  extends: string[];
  properties: PropertyInfo[];
  methods: FunctionSignature[];
  docComment: string | null;
  startLine: number;
  endLine: number;
}

export interface TypeInfo {
  name: string;
  isExported: boolean;
  definition: string;
  docComment: string | null;
  startLine: number;
  endLine: number;
}

export interface ImportInfo {
  source: string;
  imports: Array<{ name: string; alias?: string }>;
  isDefault: boolean;
  startLine: number;
}

export interface ASTAnalysisResult {
  filePath: string;
  language: string;
  functions: FunctionSignature[];
  classes: ClassInfo[];
  interfaces: InterfaceInfo[];
  types: TypeInfo[];
  imports: ImportInfo[];
  exports: string[];
  contentHash: string;
  lastModified: string;
  linesOfCode: number;
  complexity: number;
}

export interface CodeDiff {
  type: "added" | "removed" | "modified" | "unchanged";
  category: "function" | "class" | "interface" | "type" | "import" | "export";
  name: string;
  details: string;
  oldSignature?: string;
  newSignature?: string;
  impactLevel: "breaking" | "major" | "minor" | "patch";
}

/**
 * Call graph node representing a function and its calls (Issue #72)
 */
export interface CallGraphNode {
  /** Function signature with full metadata */
  function: FunctionSignature;
  /** File location of this function */
  location: {
    file: string;
    line: number;
    column?: number;
  };
  /** Child function calls made by this function */
  calls: CallGraphNode[];
  /** Conditional branches (if/else, switch) with their paths */
  conditionalBranches: ConditionalPath[];
  /** Exception types that can be raised */
  exceptions: ExceptionPath[];
  /** Current recursion depth */
  depth: number;
  /** Whether this node was truncated due to maxDepth */
  truncated: boolean;
  /** Whether this is an external/imported function */
  isExternal: boolean;
  /** Source of the import if external */
  importSource?: string;
}

/**
 * Conditional execution path (if/else, switch, ternary)
 */
export interface ConditionalPath {
  /** Type of conditional */
  type: "if" | "else-if" | "else" | "switch-case" | "ternary";
  /** The condition expression as string */
  condition: string;
  /** Line number of the conditional */
  lineNumber: number;
  /** Functions called in the true/case branch */
  trueBranch: CallGraphNode[];
  /** Functions called in the false/else branch */
  falseBranch: CallGraphNode[];
}

/**
 * Exception path tracking
 */
export interface ExceptionPath {
  /** Exception type/class being thrown */
  exceptionType: string;
  /** Line number of the throw statement */
  lineNumber: number;
  /** The throw expression as string */
  expression: string;
  /** Whether this is caught within the function */
  isCaught: boolean;
}

/**
 * Complete call graph for an entry point (Issue #72)
 */
export interface CallGraph {
  /** Name of the entry point function */
  entryPoint: string;
  /** Root node of the call graph */
  root: CallGraphNode;
  /** All discovered functions in the call graph */
  allFunctions: Map<string, FunctionSignature>;
  /** Maximum depth that was actually reached */
  maxDepthReached: number;
  /** Files that were analyzed */
  analyzedFiles: string[];
  /** Circular references detected */
  circularReferences: Array<{ from: string; to: string }>;
  /** External calls that couldn't be resolved */
  unresolvedCalls: Array<{
    name: string;
    location: { file: string; line: number };
  }>;
  /** Build timestamp */
  buildTime: string;
}

/**
 * Options for building call graphs
 */
export interface CallGraphOptions {
  /** Maximum recursion depth (default: 3) */
  maxDepth?: number;
  /** Whether to resolve cross-file imports (default: true) */
  resolveImports?: boolean;
  /** Whether to extract conditional branches (default: true) */
  extractConditionals?: boolean;
  /** Whether to track exceptions (default: true) */
  trackExceptions?: boolean;
  /** File extensions to consider for import resolution */
  extensions?: string[];
}

/**
 * Main AST Analyzer class
 */
export class ASTAnalyzer {
  private parsers: Map<string, any> = new Map();
  private initialized = false;

  /**
   * Initialize tree-sitter parsers for all languages
   */
  async initialize(): Promise<void> {
    if (this.initialized) return;

    // Note: Tree-sitter initialization would happen here in a full implementation
    // For now, we're primarily using TypeScript/JavaScript parser
    // console.log(
    //   "AST Analyzer initialized with language support:",
    //   Object.keys(LANGUAGE_CONFIGS),
    // );
    this.initialized = true;
  }

  /**
   * Analyze a single file and extract AST information
   */
  async analyzeFile(filePath: string): Promise<ASTAnalysisResult | null> {
    if (!this.initialized) {
      await this.initialize();
    }

    const ext = path.extname(filePath);
    const language = this.detectLanguage(ext);

    if (!language) {
      console.warn(`Unsupported file extension: ${ext}`);
      return null;
    }

    const content = await fs.readFile(filePath, "utf-8");
    const stats = await fs.stat(filePath);

    // Use TypeScript parser for .ts/.tsx files
    if (language === "typescript" || language === "javascript") {
      return this.analyzeTypeScript(
        filePath,
        content,
        stats.mtime.toISOString(),
      );
    }

    // For other languages, use tree-sitter (placeholder)
    return this.analyzeWithTreeSitter(
      filePath,
      content,
      language,
      stats.mtime.toISOString(),
    );
  }

  /**
   * Analyze TypeScript/JavaScript using typescript-estree
   */
  private async analyzeTypeScript(
    filePath: string,
    content: string,
    lastModified: string,
  ): Promise<ASTAnalysisResult> {
    const functions: FunctionSignature[] = [];
    const classes: ClassInfo[] = [];
    const interfaces: InterfaceInfo[] = [];
    const types: TypeInfo[] = [];
    const imports: ImportInfo[] = [];
    const exports: string[] = [];

    try {
      const ast = parseTypeScript(content, {
        loc: true,
        range: true,
        tokens: false,
        comment: true,
        jsx: filePath.endsWith(".tsx") || filePath.endsWith(".jsx"),
      });

      // Extract functions
      this.extractFunctions(ast, content, functions);

      // Extract classes
      this.extractClasses(ast, content, classes);

      // Extract interfaces
      this.extractInterfaces(ast, content, interfaces);

      // Extract type aliases
      this.extractTypes(ast, content, types);

      // Extract imports
      this.extractImports(ast, imports);

      // Extract exports
      this.extractExports(ast, exports);
    } catch (error) {
      console.warn(`Failed to parse TypeScript file ${filePath}:`, error);
    }

    const contentHash = crypto
      .createHash("sha256")
      .update(content)
      .digest("hex");
    const linesOfCode = content.split("\n").length;
    const complexity = this.calculateComplexity(functions, classes);

    return {
      filePath,
      language:
        filePath.endsWith(".ts") || filePath.endsWith(".tsx")
          ? "typescript"
          : "javascript",
      functions,
      classes,
      interfaces,
      types,
      imports,
      exports,
      contentHash,
      lastModified,
      linesOfCode,
      complexity,
    };
  }

  /**
   * Analyze using tree-sitter (placeholder for other languages)
   */
  private async analyzeWithTreeSitter(
    filePath: string,
    content: string,
    language: string,
    lastModified: string,
  ): Promise<ASTAnalysisResult> {
    // Placeholder for tree-sitter analysis
    // In a full implementation, we'd parse the content using tree-sitter
    // and extract language-specific constructs

    const contentHash = crypto
      .createHash("sha256")
      .update(content)
      .digest("hex");
    const linesOfCode = content.split("\n").length;

    return {
      filePath,
      language,
      functions: [],
      classes: [],
      interfaces: [],
      types: [],
      imports: [],
      exports: [],
      contentHash,
      lastModified,
      linesOfCode,
      complexity: 0,
    };
  }

  /**
   * Extract function declarations from AST
   */
  private extractFunctions(
    ast: any,
    content: string,
    functions: FunctionSignature[],
  ): void {
    const lines = content.split("\n");

    const traverse = (node: any, isExported = false) => {
      if (!node) return;

      // Handle export declarations
      if (
        node.type === "ExportNamedDeclaration" ||
        node.type === "ExportDefaultDeclaration"
      ) {
        if (node.declaration) {
          traverse(node.declaration, true);
        }
        return;
      }

      // Function declarations
      if (node.type === "FunctionDeclaration") {
        const func = this.parseFunctionNode(node, lines, isExported);
        if (func) functions.push(func);
      }

      // Arrow functions assigned to variables
      if (node.type === "VariableDeclaration") {
        for (const declarator of node.declarations || []) {
          if (declarator.init?.type === "ArrowFunctionExpression") {
            const func = this.parseArrowFunction(declarator, lines, isExported);
            if (func) functions.push(func);
          }
        }
      }

      // Traverse children
      for (const key in node) {
        if (typeof node[key] === "object" && node[key] !== null) {
          if (Array.isArray(node[key])) {
            node[key].forEach((child: any) => traverse(child, false));
          } else {
            traverse(node[key], false);
          }
        }
      }
    };

    traverse(ast);
  }

  /**
   * Parse function node
   */
  private parseFunctionNode(
    node: any,
    lines: string[],
    isExported: boolean,
  ): FunctionSignature | null {
    if (!node.id?.name) return null;

    const docComment = this.extractDocComment(node.loc?.start.line - 1, lines);
    const parameters = this.extractParameters(node.params);

    return {
      name: node.id.name,
      parameters,
      returnType: this.extractReturnType(node),
      isAsync: node.async || false,
      isExported,
      isPublic: true,
      docComment,
      startLine: node.loc?.start.line || 0,
      endLine: node.loc?.end.line || 0,
      complexity: this.calculateFunctionComplexity(node),
      dependencies: [],
    };
  }

  /**
   * Parse arrow function
   */
  private parseArrowFunction(
    declarator: any,
    lines: string[],
    isExported: boolean,
  ): FunctionSignature | null {
    if (!declarator.id?.name) return null;

    const node = declarator.init;
    const docComment = this.extractDocComment(
      declarator.loc?.start.line - 1,
      lines,
    );
    const parameters = this.extractParameters(node.params);

    return {
      name: declarator.id.name,
      parameters,
      returnType: this.extractReturnType(node),
      isAsync: node.async || false,
      isExported,
      isPublic: true,
      docComment,
      startLine: declarator.loc?.start.line || 0,
      endLine: declarator.loc?.end.line || 0,
      complexity: this.calculateFunctionComplexity(node),
      dependencies: [],
    };
  }

  /**
   * Extract classes from AST
   */
  private extractClasses(
    ast: any,
    content: string,
    classes: ClassInfo[],
  ): void {
    const lines = content.split("\n");

    const traverse = (node: any, isExported = false) => {
      if (!node) return;

      // Handle export declarations
      if (
        node.type === "ExportNamedDeclaration" ||
        node.type === "ExportDefaultDeclaration"
      ) {
        if (node.declaration) {
          traverse(node.declaration, true);
        }
        return;
      }

      if (node.type === "ClassDeclaration" && node.id?.name) {
        const classInfo = this.parseClassNode(node, lines, isExported);
        if (classInfo) classes.push(classInfo);
      }

      for (const key in node) {
        if (typeof node[key] === "object" && node[key] !== null) {
          if (Array.isArray(node[key])) {
            node[key].forEach((child: any) => traverse(child, false));
          } else {
            traverse(node[key], false);
          }
        }
      }
    };

    traverse(ast);
  }

  /**
   * Parse class node
   */
  private parseClassNode(
    node: any,
    lines: string[],
    isExported: boolean,
  ): ClassInfo | null {
    const methods: FunctionSignature[] = [];
    const properties: PropertyInfo[] = [];

    // Extract methods and properties
    if (node.body?.body) {
      for (const member of node.body.body) {
        if (member.type === "MethodDefinition") {
          const method = this.parseMethodNode(member, lines);
          if (method) methods.push(method);
        } else if (member.type === "PropertyDefinition") {
          const property = this.parsePropertyNode(member);
          if (property) properties.push(property);
        }
      }
    }

    return {
      name: node.id.name,
      isExported,
      extends: node.superClass?.name || null,
      implements:
        node.implements?.map((i: any) => i.expression?.name || "unknown") || [],
      methods,
      properties,
      docComment: this.extractDocComment(node.loc?.start.line - 1, lines),
      startLine: node.loc?.start.line || 0,
      endLine: node.loc?.end.line || 0,
    };
  }

  /**
   * Parse method node
   */
  private parseMethodNode(
    node: any,
    lines: string[],
  ): FunctionSignature | null {
    if (!node.key?.name) return null;

    return {
      name: node.key.name,
      parameters: this.extractParameters(node.value?.params || []),
      returnType: this.extractReturnType(node.value),
      isAsync: node.value?.async || false,
      isExported: false,
      isPublic: !node.key.name.startsWith("_"),
      docComment: this.extractDocComment(node.loc?.start.line - 1, lines),
      startLine: node.loc?.start.line || 0,
      endLine: node.loc?.end.line || 0,
      complexity: this.calculateFunctionComplexity(node.value),
      dependencies: [],
    };
  }

  /**
   * Parse property node
   */
  private parsePropertyNode(node: any): PropertyInfo | null {
    if (!node.key?.name) return null;

    return {
      name: node.key.name,
      type: this.extractTypeAnnotation(node.typeAnnotation),
      isStatic: node.static || false,
      isReadonly: node.readonly || false,
      visibility: this.determineVisibility(node),
    };
  }

  /**
   * Extract interfaces from AST
   */
  private extractInterfaces(
    ast: any,
    content: string,
    interfaces: InterfaceInfo[],
  ): void {
    const lines = content.split("\n");

    const traverse = (node: any, isExported = false) => {
      if (!node) return;

      // Handle export declarations
      if (
        node.type === "ExportNamedDeclaration" ||
        node.type === "ExportDefaultDeclaration"
      ) {
        if (node.declaration) {
          traverse(node.declaration, true);
        }
        return;
      }

      if (node.type === "TSInterfaceDeclaration" && node.id?.name) {
        const interfaceInfo = this.parseInterfaceNode(node, lines, isExported);
        if (interfaceInfo) interfaces.push(interfaceInfo);
      }

      for (const key in node) {
        if (typeof node[key] === "object" && node[key] !== null) {
          if (Array.isArray(node[key])) {
            node[key].forEach((child: any) => traverse(child, false));
          } else {
            traverse(node[key], false);
          }
        }
      }
    };

    traverse(ast);
  }

  /**
   * Parse interface node
   */
  private parseInterfaceNode(
    node: any,
    lines: string[],
    isExported: boolean,
  ): InterfaceInfo | null {
    const properties: PropertyInfo[] = [];
    const methods: FunctionSignature[] = [];

    if (node.body?.body) {
      for (const member of node.body.body) {
        if (member.type === "TSPropertySignature") {
          const prop = this.parseInterfaceProperty(member);
          if (prop) properties.push(prop);
        } else if (member.type === "TSMethodSignature") {
          const method = this.parseInterfaceMethod(member);
          if (method) methods.push(method);
        }
      }
    }

    return {
      name: node.id.name,
      isExported,
      extends:
        node.extends?.map((e: any) => e.expression?.name || "unknown") || [],
      properties,
      methods,
      docComment: this.extractDocComment(node.loc?.start.line - 1, lines),
      startLine: node.loc?.start.line || 0,
      endLine: node.loc?.end.line || 0,
    };
  }

  /**
   * Parse interface property
   */
  private parseInterfaceProperty(node: any): PropertyInfo | null {
    if (!node.key?.name) return null;

    return {
      name: node.key.name,
      type: this.extractTypeAnnotation(node.typeAnnotation),
      isStatic: false,
      isReadonly: node.readonly || false,
      visibility: "public",
    };
  }

  /**
   * Parse interface method
   */
  private parseInterfaceMethod(node: any): FunctionSignature | null {
    if (!node.key?.name) return null;

    return {
      name: node.key.name,
      parameters: this.extractParameters(node.params || []),
      returnType: this.extractTypeAnnotation(node.returnType),
      isAsync: false,
      isExported: false,
      isPublic: true,
      docComment: null,
      startLine: node.loc?.start.line || 0,
      endLine: node.loc?.end.line || 0,
      complexity: 0,
      dependencies: [],
    };
  }

  /**
   * Extract type aliases from AST
   */
  private extractTypes(ast: any, content: string, types: TypeInfo[]): void {
    const lines = content.split("\n");

    const traverse = (node: any, isExported = false) => {
      if (!node) return;

      // Handle export declarations
      if (
        node.type === "ExportNamedDeclaration" ||
        node.type === "ExportDefaultDeclaration"
      ) {
        if (node.declaration) {
          traverse(node.declaration, true);
        }
        return;
      }

      if (node.type === "TSTypeAliasDeclaration" && node.id?.name) {
        const typeInfo = this.parseTypeNode(node, lines, isExported);
        if (typeInfo) types.push(typeInfo);
      }

      for (const key in node) {
        if (typeof node[key] === "object" && node[key] !== null) {
          if (Array.isArray(node[key])) {
            node[key].forEach((child: any) => traverse(child, false));
          } else {
            traverse(node[key], false);
          }
        }
      }
    };

    traverse(ast);
  }

  /**
   * Parse type alias node
   */
  private parseTypeNode(
    node: any,
    lines: string[],
    isExported: boolean,
  ): TypeInfo | null {
    return {
      name: node.id.name,
      isExported,
      definition: this.extractTypeDefinition(node.typeAnnotation),
      docComment: this.extractDocComment(node.loc?.start.line - 1, lines),
      startLine: node.loc?.start.line || 0,
      endLine: node.loc?.end.line || 0,
    };
  }

  /**
   * Extract imports from AST
   */
  private extractImports(ast: any, imports: ImportInfo[]): void {
    const traverse = (node: any) => {
      if (!node) return;

      if (node.type === "ImportDeclaration") {
        const importInfo: ImportInfo = {
          source: node.source?.value || "",
          imports: [],
          isDefault: false,
          startLine: node.loc?.start.line || 0,
        };

        for (const specifier of node.specifiers || []) {
          if (specifier.type === "ImportDefaultSpecifier") {
            importInfo.isDefault = true;
            importInfo.imports.push({
              name: specifier.local?.name || "default",
            });
          } else if (specifier.type === "ImportSpecifier") {
            importInfo.imports.push({
              name: specifier.imported?.name || "",
              alias:
                specifier.local?.name !== specifier.imported?.name
                  ? specifier.local?.name
                  : undefined,
            });
          }
        }

        imports.push(importInfo);
      }

      for (const key in node) {
        if (typeof node[key] === "object" && node[key] !== null) {
          if (Array.isArray(node[key])) {
            node[key].forEach((child: any) => traverse(child));
          } else {
            traverse(node[key]);
          }
        }
      }
    };

    traverse(ast);
  }

  /**
   * Extract exports from AST
   */
  private extractExports(ast: any, exports: string[]): void {
    const traverse = (node: any) => {
      if (!node) return;

      // Named exports
      if (node.type === "ExportNamedDeclaration") {
        if (node.declaration) {
          if (node.declaration.id?.name) {
            exports.push(node.declaration.id.name);
          } else if (node.declaration.declarations) {
            for (const decl of node.declaration.declarations) {
              if (decl.id?.name) exports.push(decl.id.name);
            }
          }
        }
        for (const specifier of node.specifiers || []) {
          if (specifier.exported?.name) exports.push(specifier.exported.name);
        }
      }

      // Default export
      if (node.type === "ExportDefaultDeclaration") {
        if (node.declaration?.id?.name) {
          exports.push(node.declaration.id.name);
        } else {
          exports.push("default");
        }
      }

      for (const key in node) {
        if (typeof node[key] === "object" && node[key] !== null) {
          if (Array.isArray(node[key])) {
            node[key].forEach((child: any) => traverse(child));
          } else {
            traverse(node[key]);
          }
        }
      }
    };

    traverse(ast);
  }

  // Helper methods

  private extractParameters(params: any[]): ParameterInfo[] {
    return params.map((param) => ({
      name: param.name || param.argument?.name || param.left?.name || "unknown",
      type: this.extractTypeAnnotation(param.typeAnnotation),
      optional: param.optional || false,
      defaultValue: param.right ? this.extractDefaultValue(param.right) : null,
    }));
  }

  private extractReturnType(node: any): string | null {
    return this.extractTypeAnnotation(node?.returnType);
  }

  private extractTypeAnnotation(typeAnnotation: any): string | null {
    if (!typeAnnotation) return null;
    if (typeAnnotation.typeAnnotation)
      return this.extractTypeDefinition(typeAnnotation.typeAnnotation);
    return this.extractTypeDefinition(typeAnnotation);
  }

  private extractTypeDefinition(typeNode: any): string {
    if (!typeNode) return "unknown";
    if (typeNode.type === "TSStringKeyword") return "string";
    if (typeNode.type === "TSNumberKeyword") return "number";
    if (typeNode.type === "TSBooleanKeyword") return "boolean";
    if (typeNode.type === "TSAnyKeyword") return "any";
    if (typeNode.type === "TSVoidKeyword") return "void";
    if (typeNode.type === "TSTypeReference")
      return typeNode.typeName?.name || "unknown";
    return "unknown";
  }

  private extractDefaultValue(node: any): string | null {
    if (node.type === "Literal") return String(node.value);
    if (node.type === "Identifier") return node.name;
    return null;
  }

  private extractDocComment(
    lineNumber: number,
    lines: string[],
  ): string | null {
    if (lineNumber < 0 || lineNumber >= lines.length) return null;

    const comment: string[] = [];
    let currentLine = lineNumber;

    // Look backwards for JSDoc comment
    while (currentLine >= 0) {
      const line = lines[currentLine].trim();
      if (line.startsWith("*/")) {
        comment.unshift(line);
        currentLine--;
        continue;
      }
      if (line.startsWith("*") || line.startsWith("/**")) {
        comment.unshift(line);
        if (line.startsWith("/**")) break;
        currentLine--;
        continue;
      }
      if (comment.length > 0) break;
      currentLine--;
    }

    return comment.length > 0 ? comment.join("\n") : null;
  }

  private isExported(node: any): boolean {
    if (!node) return false;

    // Check parent for export
    let current = node;
    while (current) {
      if (
        current.type === "ExportNamedDeclaration" ||
        current.type === "ExportDefaultDeclaration"
      ) {
        return true;
      }
      current = current.parent;
    }

    return false;
  }

  private determineVisibility(node: any): "public" | "private" | "protected" {
    if (node.accessibility) return node.accessibility;
    if (node.key?.name?.startsWith("_")) return "private";
    if (node.key?.name?.startsWith("#")) return "private";
    return "public";
  }

  private calculateFunctionComplexity(node: any): number {
    // Simplified cyclomatic complexity
    let complexity = 1;

    const traverse = (n: any) => {
      if (!n) return;

      // Increment for control flow statements
      if (
        [
          "IfStatement",
          "ConditionalExpression",
          "ForStatement",
          "WhileStatement",
          "DoWhileStatement",
          "SwitchCase",
          "CatchClause",
        ].includes(n.type)
      ) {
        complexity++;
      }

      for (const key in n) {
        if (typeof n[key] === "object" && n[key] !== null) {
          if (Array.isArray(n[key])) {
            n[key].forEach((child: any) => traverse(child));
          } else {
            traverse(n[key]);
          }
        }
      }
    };

    traverse(node);
    return complexity;
  }

  private calculateComplexity(
    functions: FunctionSignature[],
    classes: ClassInfo[],
  ): number {
    const functionComplexity = functions.reduce(
      (sum, f) => sum + f.complexity,
      0,
    );
    const classComplexity = classes.reduce(
      (sum, c) =>
        sum + c.methods.reduce((methodSum, m) => methodSum + m.complexity, 0),
      0,
    );
    return functionComplexity + classComplexity;
  }

  private detectLanguage(ext: string): string | null {
    for (const [lang, config] of Object.entries(LANGUAGE_CONFIGS)) {
      if (config.extensions.includes(ext)) return lang;
    }
    return null;
  }

  /**
   * Compare two AST analysis results and detect changes
   */
  async detectDrift(
    oldAnalysis: ASTAnalysisResult,
    newAnalysis: ASTAnalysisResult,
  ): Promise<CodeDiff[]> {
    const diffs: CodeDiff[] = [];

    // Compare functions
    diffs.push(
      ...this.compareFunctions(oldAnalysis.functions, newAnalysis.functions),
    );

    // Compare classes
    diffs.push(
      ...this.compareClasses(oldAnalysis.classes, newAnalysis.classes),
    );

    // Compare interfaces
    diffs.push(
      ...this.compareInterfaces(oldAnalysis.interfaces, newAnalysis.interfaces),
    );

    // Compare types
    diffs.push(...this.compareTypes(oldAnalysis.types, newAnalysis.types));

    return diffs;
  }

  private compareFunctions(
    oldFuncs: FunctionSignature[],
    newFuncs: FunctionSignature[],
  ): CodeDiff[] {
    const diffs: CodeDiff[] = [];
    const oldMap = new Map(oldFuncs.map((f) => [f.name, f]));
    const newMap = new Map(newFuncs.map((f) => [f.name, f]));

    // Check for removed functions
    for (const [name, func] of oldMap) {
      if (!newMap.has(name)) {
        diffs.push({
          type: "removed",
          category: "function",
          name,
          details: `Function '${name}' was removed`,
          oldSignature: this.formatFunctionSignature(func),
          impactLevel: func.isExported ? "breaking" : "minor",
        });
      }
    }

    // Check for added functions
    for (const [name, func] of newMap) {
      if (!oldMap.has(name)) {
        diffs.push({
          type: "added",
          category: "function",
          name,
          details: `Function '${name}' was added`,
          newSignature: this.formatFunctionSignature(func),
          impactLevel: "patch",
        });
      }
    }

    // Check for modified functions
    for (const [name, newFunc] of newMap) {
      const oldFunc = oldMap.get(name);
      if (oldFunc) {
        const changes = this.detectFunctionChanges(oldFunc, newFunc);
        if (changes.length > 0) {
          diffs.push({
            type: "modified",
            category: "function",
            name,
            details: changes.join("; "),
            oldSignature: this.formatFunctionSignature(oldFunc),
            newSignature: this.formatFunctionSignature(newFunc),
            impactLevel: this.determineFunctionImpact(oldFunc, newFunc),
          });
        }
      }
    }

    return diffs;
  }

  private compareClasses(
    oldClasses: ClassInfo[],
    newClasses: ClassInfo[],
  ): CodeDiff[] {
    const diffs: CodeDiff[] = [];
    const oldMap = new Map(oldClasses.map((c) => [c.name, c]));
    const newMap = new Map(newClasses.map((c) => [c.name, c]));

    for (const [name, oldClass] of oldMap) {
      if (!newMap.has(name)) {
        diffs.push({
          type: "removed",
          category: "class",
          name,
          details: `Class '${name}' was removed`,
          impactLevel: oldClass.isExported ? "breaking" : "minor",
        });
      }
    }

    for (const [name] of newMap) {
      if (!oldMap.has(name)) {
        diffs.push({
          type: "added",
          category: "class",
          name,
          details: `Class '${name}' was added`,
          impactLevel: "patch",
        });
      }
    }

    return diffs;
  }

  private compareInterfaces(
    oldInterfaces: InterfaceInfo[],
    newInterfaces: InterfaceInfo[],
  ): CodeDiff[] {
    const diffs: CodeDiff[] = [];
    const oldMap = new Map(oldInterfaces.map((i) => [i.name, i]));
    const newMap = new Map(newInterfaces.map((i) => [i.name, i]));

    for (const [name, oldInterface] of oldMap) {
      if (!newMap.has(name)) {
        diffs.push({
          type: "removed",
          category: "interface",
          name,
          details: `Interface '${name}' was removed`,
          impactLevel: oldInterface.isExported ? "breaking" : "minor",
        });
      }
    }

    for (const [name] of newMap) {
      if (!oldMap.has(name)) {
        diffs.push({
          type: "added",
          category: "interface",
          name,
          details: `Interface '${name}' was added`,
          impactLevel: "patch",
        });
      }
    }

    return diffs;
  }

  private compareTypes(oldTypes: TypeInfo[], newTypes: TypeInfo[]): CodeDiff[] {
    const diffs: CodeDiff[] = [];
    const oldMap = new Map(oldTypes.map((t) => [t.name, t]));
    const newMap = new Map(newTypes.map((t) => [t.name, t]));

    for (const [name, oldType] of oldMap) {
      if (!newMap.has(name)) {
        diffs.push({
          type: "removed",
          category: "type",
          name,
          details: `Type '${name}' was removed`,
          impactLevel: oldType.isExported ? "breaking" : "minor",
        });
      }
    }

    for (const [name] of newMap) {
      if (!oldMap.has(name)) {
        diffs.push({
          type: "added",
          category: "type",
          name,
          details: `Type '${name}' was added`,
          impactLevel: "patch",
        });
      }
    }

    return diffs;
  }

  private detectFunctionChanges(
    oldFunc: FunctionSignature,
    newFunc: FunctionSignature,
  ): string[] {
    const changes: string[] = [];

    // Check parameter changes
    if (oldFunc.parameters.length !== newFunc.parameters.length) {
      changes.push(
        `Parameter count changed from ${oldFunc.parameters.length} to ${newFunc.parameters.length}`,
      );
    }

    // Check return type changes
    if (oldFunc.returnType !== newFunc.returnType) {
      changes.push(
        `Return type changed from '${oldFunc.returnType}' to '${newFunc.returnType}'`,
      );
    }

    // Check async changes
    if (oldFunc.isAsync !== newFunc.isAsync) {
      changes.push(
        newFunc.isAsync
          ? "Function became async"
          : "Function is no longer async",
      );
    }

    // Check export changes
    if (oldFunc.isExported !== newFunc.isExported) {
      changes.push(
        newFunc.isExported
          ? "Function is now exported"
          : "Function is no longer exported",
      );
    }

    return changes;
  }

  private determineFunctionImpact(
    oldFunc: FunctionSignature,
    newFunc: FunctionSignature,
  ): "breaking" | "major" | "minor" | "patch" {
    // Breaking changes
    if (oldFunc.isExported) {
      if (oldFunc.parameters.length !== newFunc.parameters.length)
        return "breaking";
      if (oldFunc.returnType !== newFunc.returnType) return "breaking";
      // If a function was exported and is no longer exported, that's breaking
      if (oldFunc.isExported && !newFunc.isExported) return "breaking";
    }

    // Major changes
    if (oldFunc.isAsync !== newFunc.isAsync) return "major";

    // Minor changes (new API surface)
    // If a function becomes exported, that's a minor change (new feature/API)
    if (!oldFunc.isExported && newFunc.isExported) return "minor";

    return "patch";
  }

  private formatFunctionSignature(func: FunctionSignature): string {
    const params = func.parameters
      .map((p) => `${p.name}: ${p.type || "any"}`)
      .join(", ");
    const returnType = func.returnType || "void";
    const asyncPrefix = func.isAsync ? "async " : "";
    return `${asyncPrefix}${func.name}(${params}): ${returnType}`;
  }

  // ============================================================================
  // Call Graph Builder (Issue #72)
  // ============================================================================

  /**
   * Build a call graph starting from an entry function
   *
   * @param entryFunction - Name of the function to start from
   * @param projectPath - Root path of the project for cross-file resolution
   * @param options - Call graph building options
   * @returns Complete call graph with all discovered paths
   */
  async buildCallGraph(
    entryFunction: string,
    projectPath: string,
    options: CallGraphOptions = {},
  ): Promise<CallGraph> {
    const resolvedOptions: Required<CallGraphOptions> = {
      maxDepth: options.maxDepth ?? 3,
      resolveImports: options.resolveImports ?? true,
      extractConditionals: options.extractConditionals ?? true,
      trackExceptions: options.trackExceptions ?? true,
      extensions: options.extensions ?? [".ts", ".tsx", ".js", ".jsx", ".mjs"],
    };

    if (!this.initialized) {
      await this.initialize();
    }

    // Find the entry file containing the function
    const entryFile = await this.findFunctionFile(
      entryFunction,
      projectPath,
      resolvedOptions.extensions,
    );

    if (!entryFile) {
      return this.createEmptyCallGraph(entryFunction);
    }

    // Analyze the entry file
    const entryAnalysis = await this.analyzeFile(entryFile);
    if (!entryAnalysis) {
      return this.createEmptyCallGraph(entryFunction);
    }

    const entryFunc = entryAnalysis.functions.find(
      (f) => f.name === entryFunction,
    );
    if (!entryFunc) {
      // Check class methods
      for (const cls of entryAnalysis.classes) {
        const method = cls.methods.find((m) => m.name === entryFunction);
        if (method) {
          return this.buildCallGraphFromFunction(
            method,
            entryFile,
            entryAnalysis,
            projectPath,
            resolvedOptions,
          );
        }
      }
      return this.createEmptyCallGraph(entryFunction);
    }

    return this.buildCallGraphFromFunction(
      entryFunc,
      entryFile,
      entryAnalysis,
      projectPath,
      resolvedOptions,
    );
  }

  /**
   * Build call graph from a specific function
   */
  private async buildCallGraphFromFunction(
    entryFunc: FunctionSignature,
    entryFile: string,
    entryAnalysis: ASTAnalysisResult,
    projectPath: string,
    options: Required<CallGraphOptions>,
  ): Promise<CallGraph> {
    const allFunctions = new Map<string, FunctionSignature>();
    const analyzedFiles: string[] = [entryFile];
    const circularReferences: Array<{ from: string; to: string }> = [];
    const unresolvedCalls: Array<{
      name: string;
      location: { file: string; line: number };
    }> = [];

    // Cache for analyzed files
    const analysisCache = new Map<string, ASTAnalysisResult>();
    analysisCache.set(entryFile, entryAnalysis);

    // Track visited functions to prevent infinite loops
    const visited = new Set<string>();
    let maxDepthReached = 0;

    const root = await this.buildCallGraphNode(
      entryFunc,
      entryFile,
      entryAnalysis,
      projectPath,
      options,
      0,
      visited,
      allFunctions,
      analysisCache,
      circularReferences,
      unresolvedCalls,
      analyzedFiles,
      (depth) => {
        maxDepthReached = Math.max(maxDepthReached, depth);
      },
    );

    return {
      entryPoint: entryFunc.name,
      root,
      allFunctions,
      maxDepthReached,
      analyzedFiles: [...new Set(analyzedFiles)],
      circularReferences,
      unresolvedCalls,
      buildTime: new Date().toISOString(),
    };
  }

  /**
   * Build a single call graph node recursively
   */
  private async buildCallGraphNode(
    func: FunctionSignature,
    filePath: string,
    analysis: ASTAnalysisResult,
    projectPath: string,
    options: Required<CallGraphOptions>,
    depth: number,
    visited: Set<string>,
    allFunctions: Map<string, FunctionSignature>,
    analysisCache: Map<string, ASTAnalysisResult>,
    circularReferences: Array<{ from: string; to: string }>,
    unresolvedCalls: Array<{
      name: string;
      location: { file: string; line: number };
    }>,
    analyzedFiles: string[],
    updateMaxDepth: (depth: number) => void,
  ): Promise<CallGraphNode> {
    const funcKey = `${filePath}:${func.name}`;
    updateMaxDepth(depth);

    // Check for circular reference
    if (visited.has(funcKey)) {
      circularReferences.push({ from: funcKey, to: func.name });
      return this.createTruncatedNode(func, filePath, depth, true);
    }

    // Check max depth
    if (depth >= options.maxDepth) {
      return this.createTruncatedNode(func, filePath, depth, false);
    }

    visited.add(funcKey);
    allFunctions.set(func.name, func);

    // Read the file content to extract function body
    let content: string;
    try {
      content = await fs.readFile(filePath, "utf-8");
    } catch {
      return this.createTruncatedNode(func, filePath, depth, false);
    }

    // Parse the function body to find calls, conditionals, and exceptions
    const functionBody = this.extractFunctionBody(content, func);
    const callExpressions = this.extractCallExpressions(
      functionBody,
      func.startLine,
    );
    const conditionalBranches: ConditionalPath[] = options.extractConditionals
      ? await this.extractConditionalPaths(
          functionBody,
          func.startLine,
          analysis,
          filePath,
          projectPath,
          options,
          depth,
          visited,
          allFunctions,
          analysisCache,
          circularReferences,
          unresolvedCalls,
          analyzedFiles,
          updateMaxDepth,
        )
      : [];
    const exceptions: ExceptionPath[] = options.trackExceptions
      ? this.extractExceptions(functionBody, func.startLine)
      : [];

    // Build child nodes for each call
    const calls: CallGraphNode[] = [];
    for (const call of callExpressions) {
      const childNode = await this.resolveAndBuildChildNode(
        call,
        filePath,
        analysis,
        projectPath,
        options,
        depth + 1,
        visited,
        allFunctions,
        analysisCache,
        circularReferences,
        unresolvedCalls,
        analyzedFiles,
        updateMaxDepth,
      );
      if (childNode) {
        calls.push(childNode);
      }
    }

    visited.delete(funcKey); // Allow revisiting from different paths

    return {
      function: func,
      location: {
        file: filePath,
        line: func.startLine,
      },
      calls,
      conditionalBranches,
      exceptions,
      depth,
      truncated: false,
      isExternal: false,
    };
  }

  /**
   * Resolve a function call and build its child node
   */
  private async resolveAndBuildChildNode(
    call: { name: string; line: number; isMethod: boolean; object?: string },
    currentFile: string,
    currentAnalysis: ASTAnalysisResult,
    projectPath: string,
    options: Required<CallGraphOptions>,
    depth: number,
    visited: Set<string>,
    allFunctions: Map<string, FunctionSignature>,
    analysisCache: Map<string, ASTAnalysisResult>,
    circularReferences: Array<{ from: string; to: string }>,
    unresolvedCalls: Array<{
      name: string;
      location: { file: string; line: number };
    }>,
    analyzedFiles: string[],
    updateMaxDepth: (depth: number) => void,
  ): Promise<CallGraphNode | null> {
    // First, try to find the function in the current file
    let targetFunc = currentAnalysis.functions.find(
      (f) => f.name === call.name,
    );
    let targetFile = currentFile;
    let targetAnalysis = currentAnalysis;

    // Check class methods if it's a method call
    if (!targetFunc && call.isMethod) {
      for (const cls of currentAnalysis.classes) {
        const method = cls.methods.find((m) => m.name === call.name);
        if (method) {
          targetFunc = method;
          break;
        }
      }
    }

    // If not found locally, try to resolve from imports
    if (!targetFunc && options.resolveImports) {
      const resolvedImport = await this.resolveImportedFunction(
        call.name,
        currentAnalysis.imports,
        currentFile,
        projectPath,
        options.extensions,
        analysisCache,
        analyzedFiles,
      );

      if (resolvedImport) {
        targetFunc = resolvedImport.func;
        targetFile = resolvedImport.file;
        targetAnalysis = resolvedImport.analysis;
      }
    }

    if (!targetFunc) {
      // Track as unresolved call (might be built-in or external library)
      if (!this.isBuiltInFunction(call.name)) {
        unresolvedCalls.push({
          name: call.name,
          location: { file: currentFile, line: call.line },
        });
      }
      return null;
    }

    return this.buildCallGraphNode(
      targetFunc,
      targetFile,
      targetAnalysis,
      projectPath,
      options,
      depth,
      visited,
      allFunctions,
      analysisCache,
      circularReferences,
      unresolvedCalls,
      analyzedFiles,
      updateMaxDepth,
    );
  }

  /**
   * Resolve an imported function to its source file
   */
  private async resolveImportedFunction(
    funcName: string,
    imports: ImportInfo[],
    currentFile: string,
    projectPath: string,
    extensions: string[],
    analysisCache: Map<string, ASTAnalysisResult>,
    analyzedFiles: string[],
  ): Promise<{
    func: FunctionSignature;
    file: string;
    analysis: ASTAnalysisResult;
  } | null> {
    // Find the import that provides this function
    for (const imp of imports) {
      const importedItem = imp.imports.find(
        (i) => i.name === funcName || i.alias === funcName,
      );

      if (
        importedItem ||
        (imp.isDefault && imp.imports[0]?.name === funcName)
      ) {
        // Resolve the import path
        const resolvedPath = await this.resolveImportPath(
          imp.source,
          currentFile,
          projectPath,
          extensions,
        );

        if (!resolvedPath) continue;

        // Check cache first
        let analysis: ASTAnalysisResult | undefined =
          analysisCache.get(resolvedPath);
        if (!analysis) {
          const analyzedFile = await this.analyzeFile(resolvedPath);
          if (analyzedFile) {
            analysis = analyzedFile;
            analysisCache.set(resolvedPath, analysis);
            analyzedFiles.push(resolvedPath);
          }
        }

        if (!analysis) continue;

        // Find the function in the resolved file
        const func = analysis.functions.find(
          (f) => f.name === (importedItem?.name || funcName),
        );
        if (func) {
          return { func, file: resolvedPath, analysis };
        }

        // Check class methods
        for (const cls of analysis.classes) {
          const method = cls.methods.find(
            (m) => m.name === (importedItem?.name || funcName),
          );
          if (method) {
            return { func: method, file: resolvedPath, analysis };
          }
        }
      }
    }

    return null;
  }

  /**
   * Resolve an import path to an absolute file path
   */
  private async resolveImportPath(
    importSource: string,
    currentFile: string,
    projectPath: string,
    extensions: string[],
  ): Promise<string | null> {
    // Skip node_modules and external packages
    if (
      !importSource.startsWith(".") &&
      !importSource.startsWith("/") &&
      !importSource.startsWith("@/")
    ) {
      return null;
    }

    const currentDir = path.dirname(currentFile);
    let basePath: string;

    if (importSource.startsWith("@/")) {
      // Handle alias imports (common in Next.js, etc.)
      basePath = path.join(projectPath, importSource.slice(2));
    } else {
      basePath = path.resolve(currentDir, importSource);
    }

    // Try with different extensions
    const candidates = [
      basePath,
      ...extensions.map((ext) => basePath + ext),
      path.join(basePath, "index.ts"),
      path.join(basePath, "index.tsx"),
      path.join(basePath, "index.js"),
    ];

    for (const candidate of candidates) {
      try {
        await fs.access(candidate);
        return candidate;
      } catch {
        // File doesn't exist, try next
      }
    }

    return null;
  }

  /**
   * Find the file containing a function
   */
  private async findFunctionFile(
    funcName: string,
    projectPath: string,
    extensions: string[],
  ): Promise<string | null> {
    // Search common source directories
    const searchDirs = ["src", "lib", "app", "."];

    for (const dir of searchDirs) {
      const searchPath = path.join(projectPath, dir);
      try {
        const files = await this.findFilesRecursive(searchPath, extensions);
        for (const file of files) {
          const analysis = await this.analyzeFile(file);
          if (analysis) {
            const func = analysis.functions.find((f) => f.name === funcName);
            if (func) return file;

            // Check class methods
            for (const cls of analysis.classes) {
              if (cls.methods.find((m) => m.name === funcName)) {
                return file;
              }
            }
          }
        }
      } catch {
        // Directory doesn't exist, continue
      }
    }

    return null;
  }

  /**
   * Recursively find files with given extensions
   */
  private async findFilesRecursive(
    dir: string,
    extensions: string[],
    maxDepth: number = 5,
    currentDepth: number = 0,
  ): Promise<string[]> {
    if (currentDepth >= maxDepth) return [];

    const files: string[] = [];
    try {
      const entries = await fs.readdir(dir, { withFileTypes: true });

      for (const entry of entries) {
        const fullPath = path.join(dir, entry.name);

        // Skip node_modules and hidden directories
        if (
          entry.name === "node_modules" ||
          entry.name.startsWith(".") ||
          entry.name === "dist" ||
          entry.name === "build"
        ) {
          continue;
        }

        if (entry.isDirectory()) {
          files.push(
            ...(await this.findFilesRecursive(
              fullPath,
              extensions,
              maxDepth,
              currentDepth + 1,
            )),
          );
        } else if (extensions.some((ext) => entry.name.endsWith(ext))) {
          files.push(fullPath);
        }
      }
    } catch {
      // Directory access error
    }

    return files;
  }

  /**
   * Extract the body of a function from source code
   */
  private extractFunctionBody(
    content: string,
    func: FunctionSignature,
  ): string {
    const lines = content.split("\n");
    return lines.slice(func.startLine - 1, func.endLine).join("\n");
  }

  /**
   * Extract function call expressions from code
   */
  private extractCallExpressions(
    code: string,
    startLine: number,
  ): Array<{ name: string; line: number; isMethod: boolean; object?: string }> {
    const calls: Array<{
      name: string;
      line: number;
      isMethod: boolean;
      object?: string;
    }> = [];

    try {
      const ast = parseTypeScript(code, {
        loc: true,
        range: true,
        tokens: false,
        comment: false,
      });

      const traverse = (node: any) => {
        if (!node) return;

        if (node.type === "CallExpression") {
          const callee = node.callee;
          const line = (node.loc?.start.line || 0) + startLine - 1;

          if (callee.type === "Identifier") {
            calls.push({
              name: callee.name,
              line,
              isMethod: false,
            });
          } else if (callee.type === "MemberExpression") {
            if (callee.property?.name) {
              calls.push({
                name: callee.property.name,
                line,
                isMethod: true,
                object: callee.object?.name,
              });
            }
          }
        }

        for (const key in node) {
          if (typeof node[key] === "object" && node[key] !== null) {
            if (Array.isArray(node[key])) {
              node[key].forEach((child: any) => traverse(child));
            } else {
              traverse(node[key]);
            }
          }
        }
      };

      traverse(ast);
    } catch {
      // Parse error, return empty
    }

    return calls;
  }

  /**
   * Extract conditional paths from function body
   */
  private async extractConditionalPaths(
    code: string,
    startLine: number,
    currentAnalysis: ASTAnalysisResult,
    currentFile: string,
    projectPath: string,
    options: Required<CallGraphOptions>,
    depth: number,
    visited: Set<string>,
    allFunctions: Map<string, FunctionSignature>,
    analysisCache: Map<string, ASTAnalysisResult>,
    circularReferences: Array<{ from: string; to: string }>,
    unresolvedCalls: Array<{
      name: string;
      location: { file: string; line: number };
    }>,
    analyzedFiles: string[],
    updateMaxDepth: (depth: number) => void,
  ): Promise<ConditionalPath[]> {
    const conditionals: ConditionalPath[] = [];

    try {
      const ast = parseTypeScript(code, {
        loc: true,
        range: true,
        tokens: false,
        comment: false,
      });

      const extractConditionString = (node: any): string => {
        if (!node) return "unknown";
        if (node.type === "Identifier") return node.name;
        if (node.type === "BinaryExpression") {
          return `${extractConditionString(node.left)} ${
            node.operator
          } ${extractConditionString(node.right)}`;
        }
        if (node.type === "MemberExpression") {
          return `${extractConditionString(node.object)}.${
            node.property?.name || "?"
          }`;
        }
        if (node.type === "UnaryExpression") {
          return `${node.operator}${extractConditionString(node.argument)}`;
        }
        if (node.type === "Literal") {
          return String(node.value);
        }
        return "complex";
      };

      const extractBranchCalls = async (
        branchNode: any,
      ): Promise<CallGraphNode[]> => {
        if (!branchNode) return [];

        const branchCode =
          branchNode.type === "BlockStatement"
            ? code.slice(branchNode.range[0], branchNode.range[1])
            : code.slice(
                branchNode.range?.[0] || 0,
                branchNode.range?.[1] || 0,
              );

        const branchCalls = this.extractCallExpressions(
          branchCode,
          (branchNode.loc?.start.line || 0) + startLine - 1,
        );
        const nodes: CallGraphNode[] = [];

        for (const call of branchCalls) {
          const childNode = await this.resolveAndBuildChildNode(
            call,
            currentFile,
            currentAnalysis,
            projectPath,
            options,
            depth + 1,
            visited,
            allFunctions,
            analysisCache,
            circularReferences,
            unresolvedCalls,
            analyzedFiles,
            updateMaxDepth,
          );
          if (childNode) {
            nodes.push(childNode);
          }
        }

        return nodes;
      };

      const traverse = async (node: any) => {
        if (!node) return;

        // If statement
        if (node.type === "IfStatement") {
          const condition = extractConditionString(node.test);
          const line = (node.loc?.start.line || 0) + startLine - 1;

          conditionals.push({
            type: "if",
            condition,
            lineNumber: line,
            trueBranch: await extractBranchCalls(node.consequent),
            falseBranch: await extractBranchCalls(node.alternate),
          });
        }

        // Switch statement
        if (node.type === "SwitchStatement") {
          const discriminant = extractConditionString(node.discriminant);

          for (const switchCase of node.cases || []) {
            conditionals.push({
              type: "switch-case",
              condition: switchCase.test
                ? `${discriminant} === ${extractConditionString(
                    switchCase.test,
                  )}`
                : "default",
              lineNumber: (switchCase.loc?.start.line || 0) + startLine - 1,
              trueBranch: await extractBranchCalls(switchCase),
              falseBranch: [],
            });
          }
        }

        // Ternary operator
        if (node.type === "ConditionalExpression") {
          const condition = extractConditionString(node.test);
          const line = (node.loc?.start.line || 0) + startLine - 1;

          conditionals.push({
            type: "ternary",
            condition,
            lineNumber: line,
            trueBranch: await extractBranchCalls(node.consequent),
            falseBranch: await extractBranchCalls(node.alternate),
          });
        }

        for (const key in node) {
          if (typeof node[key] === "object" && node[key] !== null) {
            if (Array.isArray(node[key])) {
              for (const child of node[key]) {
                await traverse(child);
              }
            } else {
              await traverse(node[key]);
            }
          }
        }
      };

      await traverse(ast);
    } catch {
      // Parse error
    }

    return conditionals;
  }

  /**
   * Extract exception paths (throw statements)
   */
  private extractExceptions(code: string, startLine: number): ExceptionPath[] {
    const exceptions: ExceptionPath[] = [];

    try {
      const ast = parseTypeScript(code, {
        loc: true,
        range: true,
        tokens: false,
        comment: false,
      });

      // Track try-catch blocks to determine if throws are caught
      const catchRanges: Array<[number, number]> = [];

      const collectCatchBlocks = (node: any) => {
        if (!node) return;

        if (node.type === "TryStatement" && node.handler) {
          const handlerRange = node.handler.range || [0, 0];
          catchRanges.push(handlerRange);
        }

        for (const key in node) {
          if (typeof node[key] === "object" && node[key] !== null) {
            if (Array.isArray(node[key])) {
              node[key].forEach((child: any) => collectCatchBlocks(child));
            } else {
              collectCatchBlocks(node[key]);
            }
          }
        }
      };

      const traverse = (node: any, inTryBlock = false) => {
        if (!node) return;

        if (node.type === "TryStatement") {
          traverse(node.block, true);
          if (node.handler) traverse(node.handler.body, false);
          if (node.finalizer) traverse(node.finalizer, false);
          return;
        }

        if (node.type === "ThrowStatement") {
          const line = (node.loc?.start.line || 0) + startLine - 1;
          const argument = node.argument;
          let exceptionType = "Error";
          let expression = "unknown";

          if (argument?.type === "NewExpression") {
            exceptionType = argument.callee?.name || "Error";
            expression = `new ${exceptionType}(...)`;
          } else if (argument?.type === "Identifier") {
            exceptionType = argument.name;
            expression = argument.name;
          } else if (argument?.type === "CallExpression") {
            exceptionType = argument.callee?.name || "Error";
            expression = `${exceptionType}(...)`;
          }

          exceptions.push({
            exceptionType,
            lineNumber: line,
            expression,
            isCaught: inTryBlock,
          });
        }

        for (const key in node) {
          if (
            key !== "handler" &&
            key !== "finalizer" &&
            typeof node[key] === "object" &&
            node[key] !== null
          ) {
            if (Array.isArray(node[key])) {
              node[key].forEach((child: any) => traverse(child, inTryBlock));
            } else {
              traverse(node[key], inTryBlock);
            }
          }
        }
      };

      collectCatchBlocks(ast);
      traverse(ast);
    } catch {
      // Parse error
    }

    return exceptions;
  }

  /**
   * Check if a function name is a built-in JavaScript function
   */
  private isBuiltInFunction(name: string): boolean {
    const builtIns = new Set([
      // Console
      "log",
      "warn",
      "error",
      "info",
      "debug",
      "trace",
      "table",
      // Array methods
      "map",
      "filter",
      "reduce",
      "forEach",
      "find",
      "findIndex",
      "some",
      "every",
      "includes",
      "indexOf",
      "push",
      "pop",
      "shift",
      "unshift",
      "slice",
      "splice",
      "concat",
      "join",
      "sort",
      "reverse",
      "flat",
      "flatMap",
      // String methods
      "split",
      "trim",
      "toLowerCase",
      "toUpperCase",
      "replace",
      "substring",
      "substr",
      "charAt",
      "startsWith",
      "endsWith",
      "padStart",
      "padEnd",
      "repeat",
      // Object methods
      "keys",
      "values",
      "entries",
      "assign",
      "freeze",
      "seal",
      "hasOwnProperty",
      // Math methods
      "max",
      "min",
      "abs",
      "floor",
      "ceil",
      "round",
      "random",
      "sqrt",
      "pow",
      // JSON
      "stringify",
      "parse",
      // Promise
      "then",
      "catch",
      "finally",
      "resolve",
      "reject",
      "all",
      "race",
      "allSettled",
      // Timers
      "setTimeout",
      "setInterval",
      "clearTimeout",
      "clearInterval",
      // Common
      "require",
      "import",
      "console",
      "Date",
      "Error",
      "Promise",
      "fetch",
    ]);
    return builtIns.has(name);
  }

  /**
   * Create an empty call graph for when entry function is not found
   */
  private createEmptyCallGraph(entryFunction: string): CallGraph {
    return {
      entryPoint: entryFunction,
      root: {
        function: {
          name: entryFunction,
          parameters: [],
          returnType: null,
          isAsync: false,
          isExported: false,
          isPublic: true,
          docComment: null,
          startLine: 0,
          endLine: 0,
          complexity: 0,
          dependencies: [],
        },
        location: { file: "unknown", line: 0 },
        calls: [],
        conditionalBranches: [],
        exceptions: [],
        depth: 0,
        truncated: false,
        isExternal: true,
      },
      allFunctions: new Map(),
      maxDepthReached: 0,
      analyzedFiles: [],
      circularReferences: [],
      unresolvedCalls: [
        {
          name: entryFunction,
          location: { file: "unknown", line: 0 },
        },
      ],
      buildTime: new Date().toISOString(),
    };
  }

  /**
   * Create a truncated node when max depth is reached or circular reference detected
   */
  private createTruncatedNode(
    func: FunctionSignature,
    filePath: string,
    depth: number,
    _isCircular: boolean,
  ): CallGraphNode {
    return {
      function: func,
      location: {
        file: filePath,
        line: func.startLine,
      },
      calls: [],
      conditionalBranches: [],
      exceptions: [],
      depth,
      truncated: true,
      isExternal: false,
    };
  }
}

```
Page 20/23FirstPrevNextLast